iOS开发iOS 开发每天分享优质文章

iOS动态修改App Icon

2019-07-31  本文已影响112人  叫我小黑

在开发过程中,我们有时候会遇到根据用户需求对项目进行更改icon的需求。具体要如何实现呢?
在 iOS 10.3 之后,苹果官方提供了相关的API来实现这个功能,主要是下面这几个方法:

@interface UIApplication (UIAlternateApplicationIcons)
// 如果为NO,表示当前进程不支持替换图标
@property (readonly, nonatomic) BOOL supportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));

// 传入nil代表使用主图标. 完成后的操作将会在任意的后台队列中异步执行; 如果需要更改UI,请确保在主队列中执行.
- (void)setAlternateIconName:(nullable NSString *)alternateIconName completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));

// 如果alternateIconName为nil,则代表当前使用的是主图标.
@property (nullable, readonly, nonatomic) NSString *alternateIconName NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
@end

具体实现步骤

1. 配置icon

添加图片icon

动态修改的icon不能放在 Assets.xcassets 里,但是正常的主icon还是可以在这里设置的,也可以按下面的方法来设置;
首先,把需要修改的icon放在一个文件夹内:


image.png

可以每种icon只放一个,也可以放多个,如果有多个尺寸的icon。

配置info.plist

新建一个key为 Icon files (iOS 5) 的字典类型item,这里的Primary Icon是设置app的主icon,可以在这里的Icon files数组内添加,有多个的话,依次添加,也可以这里不用填写,直接在Assets.xcassets 里配置

image.png
Icon files(iOS 5)内添加一个Key: CFBundleAlternateIcons ,类型为字典,在这个字典里配置我们所有需要动态修改的icon:键为icon的名称,值为一个字典,包含两个键:CFBundleIconFiles,其值类型为Array,内容为icon的名称;UIPrerenderedIcon,其值类型为bool,内容为NO,也可以不加此key
image.png
到此,info.plist的配置即完成了;

2. 代码实现

代码实现比较简单,在需要修改app icon 的地方调用下面的方法实现就行了

- (void)changeIconWithIconName:(NSString *)iconName{
    NSLog(@"%@",iconName);
    //    must be used from main thread only
    if (![[UIApplication sharedApplication] supportsAlternateIcons]) {
        //不支持动态更换icon
        return;
    }
    
    if ([iconName isEqualToString:@""] || !iconName) {
        iconName = nil;
    }
    [[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@"更换app图标发生错误了 : %@",error);
        }
    }];
}

需求基本上实现了了,但还有有一个小小的问题:就是在修改icon的时候会出来一个系统弹框.


1738688-4ad1981d8c5c3de9.png

如果不想用户操作的话,可以利用runtime动态替换方法去修改.

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method presentM = class_getInstanceMethod(self.class, @selector(presentViewController:animated:completion:));
        Method dismissM = class_getInstanceMethod(self.class, @selector(dismissAlertViewControllerPresentViewController:animated:completion:));
        //runtime 方法交换
        //通过拦截弹框事件,实现方法转换,从而去掉弹框
        method_exchangeImplementations(presentM, dismissM);
    });
}

- (void)dismissAlertViewControllerPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)animated completion:(void (^)(void))completion {
    
    if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
        UIAlertController *alertController = (UIAlertController *)viewControllerToPresent;
        if (alertController.title == nil && alertController.message == nil) {
            return;
        }
    }
    
    [self dismissAlertViewControllerPresentViewController:viewControllerToPresent animated:animated completion:completion];
}

附上本文icon修改demo,欢迎各位大大指点与批评.

上一篇下一篇

猜你喜欢

热点阅读