前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何优雅的动态修改app 图标

如何优雅的动态修改app 图标

作者头像
xiangzhihong
发布2022-11-30 11:42:38
1.4K0
发布2022-11-30 11:42:38
举报
文章被收录于专栏:向治洪

在iOS 10.3之后,苹果官方提供了相关的API来实现这个功能,主要是下面这几个方法:

代码语言:javascript
复制
@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不能放在 Assets.xcassets 里,但是正常的主icon还是可以在这里设置的,也可以按下面的方法来设置。首先,把需要修改的icon放在一个文件夹内。

这里写图片描述
这里写图片描述

如果有多个尺寸的icon,也可以直接全放进去。

2,配置info.plist

在info.plist中右键 -> Add Row ,输入Icon… 会有提示,选择Icon files(iOS 5)

这里写图片描述
这里写图片描述

这时候,内容是这样的。

这里写图片描述
这里写图片描述

这里的Primary Icon是设置app的主icon,可以在这里的Icon files数组内添加,有多个的话,依次添加,也可以这里不用填写,直接在Assets.xcassets 里配置;

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

这里写图片描述
这里写图片描述

把第一步中添加的图片全部添加进来就是这样的:

这里写图片描述
这里写图片描述

到此,info.plist的配置即完成了; 或者将info.plist文件以 Source code 方式打开,添加以下代码:

代码语言:javascript
复制
<key>CFBundleIconskey>
    <dict>
        <key>CFBundleAlternateIconskey>
        <dict>
            <key>rainkey>
            <dict>
                <key>CFBundleIconFileskey>
                <array>
                    <string>rainstring>
                array>
                <key>UIPrerenderedIconkey>
                <false/>
            dict>
            <key>snowkey>
            <dict>
                <key>CFBundleIconFileskey>
                <array>
                    <string>snowstring>
                array>
                <key>UIPrerenderedIconkey>
                <false/>
            dict>
            <key>sunshinekey>
            <dict>
                <key>CFBundleIconFileskey>
                <array>
                    <string>sunshinestring>
                array>
                <key>UIPrerenderedIconkey>
                <false/>
            dict>
            <key>cloudykey>
            <dict>
                <key>CFBundleIconFileskey>
                <array>
                    <string>cloudystring>
                array>
                <key>UIPrerenderedIconkey>
                <false/>
            dict>
        dict>
        <key>CFBundlePrimaryIconkey>
        <dict>
            <key>CFBundleIconFileskey>
            <array>
                <string>string>
            array>
            <key>UIPrerenderedIconkey>
            <false/>
        dict>
        <key>UINewsstandIconkey>
        <dict>
            <key>CFBundleIconFileskey>
            <array>
                <string>string>
            array>
            <key>UINewsstandBindingTypekey>
            <string>UINewsstandBindingTypeMagazinestring>
            <key>UINewsstandBindingEdgekey>
            <string>UINewsstandBindingEdgeLeftstring>
        dict>
    dict>

如果是添加了多个尺寸icon,也要在这里分别配置。

3,编写代码

配置完成后,代码部分就比较简单了:

代码语言:javascript
复制
- (void)changeAppIconWithName:(NSString *)iconName {
    if (![[UIApplication sharedApplication] supportsAlternateIcons]) {
        return;
    }

    if ([iconName isEqualToString:@""]) {
        iconName = nil;
    }
    [[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@"更换app图标发生错误了 : %@",error);
        }
    }];
}

在需要修改icon的地方调用这个方法,并把相应的icon名称传进去即可:

代码语言:javascript
复制
- (IBAction)snow:(id)sender {
    [self changeAppIconWithName:@"snow"];
}
- (IBAction)rain:(id)sender {
    [self changeAppIconWithName:@"rain"];
}
- (IBAction)cloudy:(id)sender {
    [self changeAppIconWithName:@"rain"];
}
- (IBAction)sunshine:(id)sender {
    [self changeAppIconWithName:@"sunshine"];
}

运行效果:

这里写图片描述
这里写图片描述

4,设置iPad动态图标

iPad的动态图标设置和上面步骤基本一样,有的文章说是将 CFBundleIcons 改为 CFBundleIcons~ipad,即:

这里写图片描述
这里写图片描述

但是,在测试中发现,使用上面的key值也是可以实现动态改变的,即不做任何修改,iPhone和iPad使用相同的配置,即:CFBundleIcons。

从上面的示意图可以发现,在设置icon的时候,会有个系统弹框,这样有时候会不太友好,我们可以使用Runtime,对UIViewController进行扩展来隐藏这个弹框:

代码语言:javascript
复制
// UIViewController+LQNoPresent.h
#import 

@interface UIViewController (LQNoPresent)

@end


// UIViewController+LQNoPresent.m

#import "UIViewController+LQNoPresent.h"
#import 

@implementation UIViewController (LQNoPresent)

+ (void)load {

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method presentM = class_getInstanceMethod(self.class, @selector(presentViewController:animated:completion:));
        Method presentSwizzlingM = class_getInstanceMethod(self.class, @selector(lq_presentViewController:animated:completion:));

        method_exchangeImplementations(presentM, presentSwizzlingM);
    });
}

- (void)lq_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {

    if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
//        NSLog(@"title : %@",((UIAlertController *)viewControllerToPresent).title);
//        NSLog(@"message : %@",((UIAlertController *)viewControllerToPresent).message);

        UIAlertController *alertController = (UIAlertController *)viewControllerToPresent;
        if (alertController.title == nil && alertController.message == nil) {
            return;
        }
    }

    [self lq_presentViewController:viewControllerToPresent animated:flag completion:completion];
}


@end

这样就没有警告弹框了。

这里写图片描述
这里写图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实例
    • 1,配置icon
      • 2,配置info.plist
        • 3,编写代码
          • 4,设置iPad动态图标
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档