改变iOS app的icon(iOS10.3)

简介: iOS10.3新增了可以让开发者去更改app的icon,接下来看看怎么更改。

改变iOS app的icon

官方

iOS10.3新增了可以让开发者去更改app的icon,接下来看看怎么更改。
官方API给的东西很少,只是介绍了一个实例方法:

open func setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Swift.Void)? = nil)

根据传入的参数可知,我们只需要传入备用icon名字即可,然后在回调里面拿到修改的结果,成功的话error为空,不成功则返回相应的错误信息(可以使用error!.localizedDescription来打印查看错误信息)。如果失败的话,alternateIconName属性不变。这里注意:

如果当期app使用的icon是备用的icon,那么这个属性的值就是当前icon的名字,这个名字是在Info.plist里面设置的名字,如果当前app展示的是主要(primary)的icon,那么这个值为nil。

这里需要注意两点:

  1. 当前设备的系统版本。这里的所有api都是10.3才能使用的。
  2. 当前app是否支持备用icon。使用supportsAlertnateIcons属性判断。只有为true的使用才能去更改。
    API中还有一句话比较关键:
你必须在Info.plist里面使用CFBundleIcons声明当前app的primary和alternate icon。这里如果不了解可以往下看,先忽略。

具体的Info.plist里面的字段含义这里就不在一一说明,详情可了解这里

总之官方API上面我只找到了这么多。然而给我的感觉反倒一脸懵逼,完全搞不懂下面的Info.plist怎么设置。因此有了下面的序文。

个人理解

在刚才的Info.plist key介绍里面,我们先看一下其他的小知识。
我们都知道在Info.plist里面有个Bundle display name,也就是设置app在桌面显示的名字。此时如果我们先不管这个key,我们继续在Info.plist里面添加CFBundleDisplayName,你会收到这样一个提示:

The key you entered is already present in the dictionary.do you want to replace the existing key/value pair?

但是看一下Info.plist字典中的key,并没有CFBundleDisplayName,替换后发现,原来它就是Bundle display name。也就是说,Info.plist里面的Key在Xcode中显示的并不是Key,而是Xcode name。如下图:
Snip20170405_2.png

这个是从官方API上截的图,其实这些Key都有对应的Xcode name,也就是在Xcodes里面我们能看到的key。其实也很简单,如果你把Info.plist使用源码形式打开(右击—>Open as —>Source code),你就会发现这里写的key就是上面列出来的key。

先看看我在网上查资料设置的Info.plist:
Snip20170405_1.png
这里的CFBundleIconFiles是备用icon的名字。下面的Primary Icon是默认的icon。源代码就是:
Snip20170406_2.png
其中CFBundleIcons对应的就是Icon files(iOS 5),CFBundleIconFiles就是Primary Icon。
先看一下CFBundleAlternateIcons。这个CFBundleAlternateIcons key所对应的value在iOS里面是一个字典,例如:
Snip20170406_3.png
每个字典的key是备用icon的名字,这个也是你传入到

IApplication.shared.setAlternateIconName(iconName) { (error) in
            if (error != nil) {
                self.aler(str: (error!.localizedDescription))
            }else {
                self.aler(str: "修改成功")
            }
        }

里面的iconName。其中的字典对应值解释如下:
Snip20170406_4.png
CFBundleIconFiles:这个是一个String的数组,里面每个元素都是icon 的名字,你可以添加多个不同大小的icon来支持iPhone,iPad。
UIPrerenderedIcon:指定应用程序的图标是否包含闪光效果(shine effect),如果icon已经有这个效果,就把这个属性设置为YES来防止系统再次添加相同效果。如果设置为NO(默认值),iOS系统会自动添加这个效果。然而,我并没有测试出来这个效果!!
这里还要注意一下:Primary Icon的Item 0的name也可以不填写,苹果官方文档也没有具体说名字这个要怎么去填写,只是说如果你想使用CFBundlePrimaryIcon键值定义的icon,直接使用将setAlternateIconName的参数alternateIconName写成nil就行。在属性列表里面直接不填写就行(即把AppIcon60x60删掉)

自己新建一个项目实现

自己实现需要注意两个问题:

  1. Info.plist怎么设置?
  2. 备用图标icon放到哪里?

首先来设置Info.plist。
按照苹果官方的API说法,那就先在Info.plist里面添加CFBundleIcons。但是查看了一下Key和Xcode name对应的表格,CFBundleIcons对应的是None,那就直接添加CFBundleIcons吧。点击Information Property List后面的加号,输入CFBundleIcons,当点击Enter键的时候,你会惊奇发现:你添加的CFBundleIcons变成了Icon files(iOS 5)字典。看看CFBundleIcons的官方API:
Snip20170406_6.png
根据英文意思可以知道:该key包含了所有app使用的icons信息。新建的是这样的:
Snip20170406_8.png
可知默认的包含了CFBundlePrimaryIcon和UINewsstandIcon。里面没有CFBundleAlternateIcons,(我理解的应该是苹果不太想支持用户添加备选icon,所以才没有)。这里不过多介绍UINewsstandIcon了,它应该是在NewStand上展示的吧,不太清楚,想了解可以看API,里面介绍了。
现在把NewStand Icon删除,添加CFBundleAlternateIcons。添加后如图所示:
Snip20170406_11.png
但是看官方API对CFBundleAlternateIcon的介绍里面,并没有UINewstandBindingType和UINewsstandBindingEdge,只有这个:
Snip20170406_12.png
也就是官网所说的只有CFBundleIconFiles和UIPrerenderedIcon,那就删了多余的那两个UINewstandBindingType和UINewsstandBindingEdge。然后添加UIPrerenderedIcon:
Snip20170406_14.png。按照苹果的说法,把备用图标的名字放到Items0里面。我们先直接在左侧导航中加入两张图片:newicon@2x.png 和newicon@3x.png,一个120 120,一个180 180。
但是看到上图说的设置,跑起来运行代码:

    @IBAction func changeToNewIconAction(_ sender: Any) {
        if !checkSupportChangeIcon() {
            return
        }
        if !UIApplication.shared.supportsAlternateIcons {
            return
        }
        changeToIcon("newicon")

    }
    //MARK: check system version
    func checkSupportChangeIcon() -> Bool {
        let deviceVersion = UIDevice.current.systemVersion
        if deviceVersion.contains("10.3") {
            return true
        }
        return false
    }
    //MARK: change to icon message
    func changeToIcon(_ iconName: String?)  {
        
        UIApplication.shared.setAlternateIconName(iconName) { (error) in
            if (error != nil) {
                self.aler(str: (error!.localizedDescription))
            }else {
                self.aler(str: "修改成功")
            }
        }
        
        
        
    }
    //MARK: alert message
    func aler(str: String) {
        let alert = UIAlertController.init(title: "提示", message: str, preferredStyle: .alert)
        let okAction = UIAlertAction.init(title: "ok", style: .cancel) { (action: UIAlertAction) in
            print("关闭弹出框")
        }
        alert.addAction(okAction)
        self.present(alert, animated: true, completion: nil)
    }

结果却是:

The file doesn't exist

看了一下官方API对CFBundleAlternateIcons的介绍,里面有一句话:

In iOS, the value of the key is a dictionary. The key for each dictionary entry is the name of the alternate icon, which is also the string you pass to the setAlternateIconName:completionHandler: method of UIApplication when changing icons. The value for each key is a dictionary containing the keys in Table 5

意思是这个CFBundleAlternateIcons中的字典的key是备用icon的名字,因此需要这样修改:
Snip20170406_15.png
也就是CFBundleAlternateIcons字典里面的key是备用icon的名字,然后以名字为key的字典里面又包含了CFBundleIconFiles和UIPrerenderedIcon。
这样设置之后再次运行你会发现成功更改了icon。
这样就成功地改变了icon。
关于Primary Icon,直接不用设置Icon files就好了,如果你想设置为默认的icon,就在setAlternateIconName里面传入nil就好了。这个时候Info.plist源码长这样:
Snip20170406_16.png
在Property List里面,Primary Icon的Icon already includes gloss effects就是UIPrerenderedIcon,它的设置为false。(这里的光泽效果也是没有测试出来有什么不一样)
接下来看看备用icon是在哪里放着呢?
开始的时候直接放到这里:
Snip20170406_17.png
发现是OK的,可以正常显示。
那么放到Assets.xcassets里面呢?放到Bundle里面呢?接下来将每个case都进行测试:

  • 放到Assets.xcassets里面。新建一个普通的Image set,然后将图片放到里面,效果如图所示:
    Snip20170406_18.png

经过测试发现,这样放置是无法正常改变appicon的。但是运行结果没有任何错误,而且系统提示里面加载的也是新的app icon:
IMG_0022.PNG

  • 放到Assets.xcassets里面,并且新建的icon,如图:
    Snip20170406_19.png

运行依然设置不成功。没有错误提示

  • 放到一个新建的Bundle里面。如图所示:。
    Snip20170406_20.png

运行结果依然是没有成功更改。没有错误提示。

所以经过测试,发现只有放到导航里面的图片才可以更改成功。在苹果qa里面看到过一个场景,他们是直接在导航新建了一个文件夹,然后将图片放到里面,然后使用。这里也推荐建立文件夹放入图片,然后使用

另外,关于icon大小,可以参见这里

最后告诉大家一个不使用Asset来配置Icon的方法:直接在Info.plist下面这样写:
Snip20170406_22.png
这个是通用的,可以直接设置iPhone和iPad的icon。其实这里也是想告诉大家:如何在CFBundleIconFiles里面去添加图片数组:

 <key>CFBundleIconFiles</key>
            <array>
                <string>Icon-Small</string>
                <string>Icon-Small-40</string>
                <string>Icon-Small-50</string>
                <string>Icon</string>
                <string>Icon-60</string>
                <string>Icon-72</string>
            </array>
备注
  1. 如果有什么疑问欢迎留言提问。或直接加群:206613455
  2. 源码地址:https://github.com/ScottZg/iOSChangeAppIcon
相关文章
|
17天前
|
API 数据安全/隐私保护 iOS开发
利用uni-app 开发的iOS app 发布到App Store全流程
利用uni-app 开发的iOS app 发布到App Store全流程
117 3
|
17天前
|
Android开发 iOS开发 开发者
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
App备案-iOS云管理式证书 Distribution Managed 公钥及证书SHA-1指纹的获取方法
178 0
|
8天前
如何解决iOS16系统app首次启动总是弹出允许粘贴提示框问题
如何解决iOS16系统app首次启动总是弹出允许粘贴提示框问题
13 0
如何解决iOS16系统app首次启动总是弹出允许粘贴提示框问题
|
8天前
|
移动开发 网络协议 Linux
We discovered one or more bugs in your app when reviewed on iPhone and iPad running iOS 14.1
We discovered one or more bugs in your app when reviewed on iPhone and iPad running iOS 14.1
14 0
|
10天前
|
定位技术 开发工具 iOS开发
ios9定位服务的app进入后台三分钟收不到经纬度,应用被挂起问题及解决方案
ios9定位服务的app进入后台三分钟收不到经纬度,应用被挂起问题及解决方案
15 0
|
10天前
|
大数据 测试技术 数据库
ios app性能分析
ios app性能分析
16 2
|
10天前
|
iOS开发 网络架构 UED
ios app的分类与本质,感想
ios app的分类与本质,感想
14 0
|
17天前
|
开发者 iOS开发
iOS App上架新规解析:如何进行App备案
iOS App上架新规解析:如何进行App备案
367 0
|
17天前
|
iOS开发 开发者
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
【教程】uni-app iOS 打包解决 profile 文件与私钥证书不匹配问题
|
iOS开发
iOS App设置icon,启动图,App名称的方法
<p style="margin-top:0px; margin-bottom:15px; color:rgb(85,85,85); font-family:'Microsoft Yahei','Helvetica Neue',Helvetica,Arial,sans-serif; font-size:14px; line-height:28px"> 每款App都要有自己的icon,和名
1276 0