第一种方式:
一、info.plist添加key
<key>CFBundleIcons</key>
<dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>Icon1</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>app_icon_tx</string>
</array>
</dict>
<key>Icon2</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>app_icon_jd</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array/>
</dict>
</dict>
显示为:
CFBundlePrimaryIcon 对应的就是默认的图标,默认图标可以不写,在Asset里面会有设置, 而Icon1、Icon2 就是我们的使用到的动态更换的图标,将动态更换的图标不能放置在asset中, 需要放到项目中以文件的形式保存.
二、动态更换图标
改API是iOS10.3以后的版本支持,低于该版本需要加判断
- (void)replaceAppIconWithIconName:(NSString *)iconName {
UIApplication *application = [UIApplication sharedApplication];
//判断系统是否支持icon的切换
if ([application supportsAlternateIcons]) {
//执行切换icon
[application setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"error==> %@",error.localizedDescription);
}else{
NSLog(@"done!!!");
}
}];
}
}
iconName 就是动态更换图标的的名称, 也就是我们在info.plist文件中制定的名称,Icon1、Icon2;
如果想切换到默认的图标如何操作呢? iconName设置为nil, 然后调用这个函数就可以实现了.
但是,如果这样更新图标,会有弹框提示用户已经更换了图标,我们更需要的是无感更换;
三、无弹框更换
无弹框更换,需要使用runtime,黑魔法hook系统的图框方法,进行拦截;
#import <objc/runtime.h>
@implementation UIViewController
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method originalPresentM = class_getInstanceMethod(self.class, @selector(presentViewController:animated:completion:));
Method swizzlingPresentM = class_getInstanceMethod(self.class, @selector(riffle_presentViewController:animated:completion:));
if (!class_addMethod([self class], @selector(riffle_presentViewController:animated:completion:), method_getImplementation(swizzlingPresentM), method_getTypeEncoding(swizzlingPresentM))) {
method_exchangeImplementations(originalPresentM, swizzlingPresentM);
}
});
}
- (void)riffle_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
UIAlertController *alertController = (UIAlertController *)viewControllerToPresent;
if (alertController.title == nil && alertController.message == nil) {
return;
} else {
[self riffle_presentViewController:viewControllerToPresent animated:flag completion:completion];
return;
}
}
[self riffle_presentViewController:viewControllerToPresent animated:flag completion:completion];
}
@end
第二种方式:
xcode13及以后版本支持
-
向Assets.xcassets内添加一组新的ICON:
2.在项目设置里的允许使用多套ICON:
选择项目->Build Setting->搜索Include all app icon assets,然后改为YES:
更换App Iocn的方法是一样的:
-(void)newReplaceAppIconWithIconName:(NSString *)iconName{
UIApplication *application = [UIApplication sharedApplication];
//判断系统是否支持icon的切换
if ([application supportsAlternateIcons]) {
//执行切换icon
[application setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"set alternative icon error:%@", error.localizedDescription);
}
}];
}
}
多套icon是需要苹果审核后才可以在苹果后台进行切换。
可以参考苹果官方文档:配置处理方案 - App Store Connect 帮助