iOS神技之动态更换APP的Icon图

iOS神技之动态更换APP的Icon图

   动态修改app的图标,就是在不重新安装app的情况下,可以修改当前的icon图标;在某些情况下,是有这个需求的;例如,可以更换主题的app中,一般都会有一套完整的主题包含相应的icon;还有就是一些节日主题的icon或者促销的icon,例如淘宝、京东等的节日icon。

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

// 如果为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));


方法很简单,但是使用之前需要进行一些配置:

1. 配置icon

添加图片icon

项目实例 demo:https://gitee.com/Jevi/changAppIcon

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


这里每种icon我只放了一个,如果有多个尺寸的icon,也可以直接全放进去:

配置info.plist

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

这时候,内容是这样的:

这里的Icon files(iOS 5)是个字典,其中可包含的Key值有CFBundlePrimaryIcon -> Primary Icon
CFBundleAlternateIcons
UINewsstandIcon -> Newsstand Icon


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

下面的Newsstand Icon,暂时用不到,不用管,也可以删除。
在 Icon files(iOS 5)内添加一个Key: CFBundleAlternateIcons ,类型为字典,在这个字典里配置我们所有需要动态修改的icon:键为icon的名称,值为一个字典(这个字典里包含两个键:CFBundleIconFiles,其值类型为Array,内容为icon的名称;UIPrerenderedIcon,其值类型为bool,内容为NO,也可以不加此key),把第一步中添加的图片全部添加进来就是这样的。例如:
 

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

<key>CFBundleIcons</key>
    <dict>
        <key>CFBundleAlternateIcons</key>
        <dict>
            <key>Sunday</key>
            <dict>
                <key>UIPrerenderedIcon</key>
                <false/>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>Sunday60x60</string>
                    <string>Sunday40x40</string>
                    <string>Sunday29x29</string>
                </array>
            </dict>
            <key>天天特价</key>
            <dict>
                <key>UIPrerenderedIcon</key>
                <false/>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>天天特价</string>
                </array>
            </dict>
            <key>小房子</key>
            <dict>
                <key>UIPrerenderedIcon</key>
                <false/>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>小房子</string>
                </array>
            </dict>
            <key>小猫</key>
            <dict>
                <key>UIPrerenderedIcon</key>
                <false/>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>小猫</string>
                </array>
            </dict>
            <key>邮件信息</key>
            <dict>
                <key>UIPrerenderedIcon</key>
                <false/>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>邮件信息</string>
                </array>
            </dict>
        </dict>
        <key>CFBundlePrimaryIcon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>默认icon</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
        <key>UINewsstandIcon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string></string>
            </array>
            <key>UINewsstandBindingType</key>
            <string>UINewsstandBindingTypeMagazine</string>
            <key>UINewsstandBindingEdge</key>
            <string>UINewsstandBindingEdgeLeft</string>
        </dict>
    </dict>

 

如果是添加了多个尺寸icon,也要在这里分别配置,以上面添加的Sunday图标为例:


使用的时候还是使用Sunday进行赋值即可!

代码

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

 NSString *imageStr = @"Sunday";
    
    if (@available(iOS 10.3, *)) {
        //判断是否支持替换图标, false: 不支持
        if (![UIApplication sharedApplication].supportsAlternateIcons) {
            return;
        }
        //如果支持, 替换icon
        [[UIApplication sharedApplication] setAlternateIconName:imageStr completionHandler:nil];
    }


####设置iPad动态图标

iPad的动态图标设置和上面步骤基本一样,有的文章说是将 CFBundleIcons 改为 CFBundleIcons~ipad,但是,在测试中发现,使用上面的key值也是可以实现动态改变的,即不做任何修改,iPhone和iPad使用相同的配置,即:CFBundleIcons。

####去掉更换icon时的弹框

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

- (void)runtimeReplaceAlert {
    
    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);
    });
}


这样在切换图标的时候就没有系统的弹框了。

参考文献:

https://blog.youkuaiyun.com/ShmilyCoder/article/details/79573720

https://www.jianshu.com/p/69313970d0e7

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值