作者:流火绯瞳
链接:https://www.jianshu.com/p/69313970d0e7
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Demo地址

https://github.com/ychexingwuji/DM_APP_Icon_Change

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

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

@interfaceUIApplication(UIAlternateApplicationIcons)// 如果为NO,表示当前进程不支持替换图标@property(readonly, nonatomic) BOOLsupportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));// 传入nil代表使用主图标. 完成后的操作将会在任意的后台队列中异步执行; 如果需要更改UI,请确保在主队列中执行.- (void)setAlternateIconName:(nullableNSString*)alternateIconName completionHandler:(nullablevoid(^)(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放在一个文件夹内:

其文件夹内是这样的

这里每种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>rain</key>
            <dict>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>rain</string>
                </array>
                <key>UIPrerenderedIcon</key>
                <false/>
            </dict>
            <key>snow</key>
            <dict>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>snow</string>
                </array>
                <key>UIPrerenderedIcon</key>
                <false/>
            </dict>
            <key>sunshine</key>
            <dict>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>sunshine</string>
                </array>
                <key>UIPrerenderedIcon</key>
                <false/>
            </dict>
            <key>cloudy</key>
            <dict>
                <key>CFBundleIconFiles</key>
                <array>
                    <string>cloudy</string>
                </array>
                <key>UIPrerenderedIcon</key>
                <false/>
            </dict>
        </dict>
        <key>CFBundlePrimaryIcon</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string></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,也要在这里分别配置,以上面添加的sunshine图标为例:

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

代码

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

- (void)changeAppIconWithName:(NSString*)iconName {if(![[UIApplicationsharedApplication] supportsAlternateIcons]) {return; }if([iconName isEqualToString:@""]) { iconName = nil; } [[UIApplicationsharedApplication] setAlternateIconName:iconName completionHandler:^(NSError* _Nullable error) {if(error) {NSLog(@"更换app图标发生错误了 : %@",error); } }]; }

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

- (IBAction)snow:(id)sender { [selfchangeAppIconWithName:@"snow"]; } - (IBAction)rain:(id)sender { [selfchangeAppIconWithName:@"rain"]; } - (IBAction)cloudy:(id)sender { [selfchangeAppIconWithName:@"rain"]; } - (IBAction)sunshine:(id)sender { [selfchangeAppIconWithName:@"sunshine"]; }

示意图:

设置iPad动态图标

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

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

去掉更换icon时的弹框

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

// UIViewController+LQNoPresent.h
#import <UIKit/UIKit.h>

@interface UIViewController (LQNoPresent)

@end

// UIViewController+LQNoPresent.m

#import "UIViewController+LQNoPresent.h"
#import <objc/runtime.h>

@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

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

iOS动态修改app 图标(icon)相关推荐

  1. iOS动态修改app图标

    动态修改app的图标,就是在不重新安装app的情况下,可以修改当前的icon图标:在某些情况下,是有这个需求的:例如,可以更换主题的app中,一般都会有一套完整的主题包含相应的icon:还有就是一些节 ...

  2. macOS app动态修改app图标,图标为icns格式

    1.macOS app动态修改app图标,图标为icns格式 //需要重启软件才能看见效果 -(void)ChangeAppIcon:(NSString *)icnsPath {if (![[NSFi ...

  3. iOS 如何修改App图标和App显示在iPhone的名字

    1. 修改App图标 1)在你的工程项目Supporting Files中找到***-Info.plist,点击进入: 2)右键找到Add Now: 3)点击Add Now之后输入Icon Files ...

  4. (0042) iOS 开发之iOS10.3新特性:如何动态更换APP图标

    iOS新特性: iOS10.3教你如何动态更换APP图标? 1.iOS 10.3 开放了更换 app 图标的 API,核心方法是下面这个: [[UIApplication sharedApplicat ...

  5. Android动态修改桌面图标新坑总结

    一.优秀文章概述 下面的文章描述动态修改桌面图标的基本方法,并且总结了很多坑及解决方案,以下是在此文章基础上的补充 <Android动态修改应用图标和名称> 二.第一个新坑 Android ...

  6. 解决Android修改APP图标无效的问题

    解决Android修改APP图标无效的问题 先说结论:这是图标适配的问题 问题描述 这是我一开始的修改方式:   修改图标后,在夜神模拟器及MIUI(Android 9)真机中正常,但在Android ...

  7. 动态修改安卓桌面icon

    动态修改安卓桌面icon 继承启动activity 网上很多说使用activity-alias的,后面看到知乎一个文章:Android动态变更图标和应用名,觉得也是写成一个activity合理一些. ...

  8. Unity动态更换APP图标及名称

    Unity动态更换APP图标及名称 参考链接:https://blog.csdn.net/fu908323236/article/details/78813136 本文环境:(本文为安卓版) Unit ...

  9. linux修改文件图标,Gnome怎么修改应用图标icon

    icon元素包括两个可选的子元素:small-icon子元素和large-icon子元素.文件名是Web应用归档文件(WAR)的根的相对路径.部署描述符并没有使用icon元素.下面跟着学习啦小编一起来 ...

最新文章

  1. keras Regressor 回归
  2. jira+mysql配置
  3. 2018-2019-2 20165114《网络对抗技术》Exp4 恶意代码分析
  4. Base64 加密字符串和文件
  5. 717. 1比特与2比特字符
  6. verilog状态机以及编码详解
  7. SQL Server 透视与逆透视转换解析
  8. 华为盒子EC6110-T-通刷-免拆刷机固件及教程
  9. JQuery提交表单form
  10. 轻巧实用的web ssh工具使用笔记——WGCLOUD
  11. Android 最常用的设计模式九 安卓源码分析—— 适配器模式(Adapter)
  12. 《三体1》6.射手和农场主
  13. 如何利用github打造博客专属域名
  14. 英特尔为RRP物联网平台项目预留1亿美元开发资金
  15. 敏捷仪式感之:敏捷宣传栏
  16. 华硕rt-n16无线打印服务器,无线打印好拍档 华硕RT-N16赠照片打印机(图)
  17. PHP网站从服务器下载文件到本地
  18. vi 从第几行到第几行 替换_vi全局替换方法:
  19. 考研英语一历年真题写作(小作文+大作文)自己练习与背诵
  20. mysql 主从同步master主数据库无法写入

热门文章

  1. C#将数值转为添加千位分隔符
  2. vue交流群,康忙北鼻 如群二维码过期,请添加群主微信
  3. SpringMVC 基础教程 简单入门实例
  4. ESXi 直通 k80 GPU到Win10
  5. 心型表白python代码
  6. (与运算)、|(或运算)、^(异或运算)
  7. ANSYS2019画弯矩图、剪力图、轴力图
  8. ReactNative系列之三十九ReactNative支持点九图
  9. 时间序列分类算法_时间序列分类算法简介
  10. SPOOLing技术的理解