改变iOS app的icon

(已被Cocoachina推荐到首页)

官方

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。如下图:

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

先看看我在网上查资料设置的Info.plist:



这里的CFBundleIconFiles是备用icon的名字。下面的Primary Icon是默认的icon。源代码就是:



其中CFBundleIcons对应的就是Icon files(iOS 5),CFBundleIconFiles就是Primary Icon。

先看一下CFBundleAlternateIcons。这个CFBundleAlternateIcons key所对应的value在iOS里面是一个字典,例如:



每个字典的key是备用icon的名字,这个也是你传入到

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

里面的iconName。其中的字典对应值解释如下:



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:



根据英文意思可以知道:该key包含了所有app使用的icons信息。新建的是这样的:



可知默认的包含了CFBundlePrimaryIcon和UINewsstandIcon。里面没有CFBundleAlternateIcons,(我理解的应该是苹果不太想支持用户添加备选icon,所以才没有)。这里不过多介绍UINewsstandIcon了,它应该是在NewStand上展示的吧,不太清楚,想了解可以看API,里面介绍了。

现在把NewStand Icon删除,添加CFBundleAlternateIcons。添加后如图所示:



但是看官方API对CFBundleAlternateIcon的介绍里面,并没有UINewstandBindingType和UINewsstandBindingEdge,只有这个:



也就是官网所说的只有CFBundleIconFiles和UIPrerenderedIcon,那就删了多余的那两个UINewstandBindingType和UINewsstandBindingEdge。然后添加UIPrerenderedIcon:

。按照苹果的说法,把备用图标的名字放到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的名字,因此需要这样修改:



也就是CFBundleAlternateIcons字典里面的key是备用icon的名字,然后以名字为key的字典里面又包含了CFBundleIconFiles和UIPrerenderedIcon。

这样设置之后再次运行你会发现成功更改了icon。

这样就成功地改变了icon。

关于Primary Icon,直接不用设置Icon files就好了,如果你想设置为默认的icon,就在setAlternateIconName里面传入nil就好了。这个时候Info.plist源码长这样:



在Property List里面,Primary Icon的Icon already includes gloss effects就是UIPrerenderedIcon,它的设置为false。(这里的光泽效果也是没有测试出来有什么不一样)

接下来看看备用icon是在哪里放着呢?

开始的时候直接放到这里:



发现是OK的,可以正常显示。

那么放到Assets.xcassets里面呢?放到Bundle里面呢?接下来将每个case都进行测试:

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



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

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



    运行依然设置不成功。没有错误提示
  • 放到一个新建的Bundle里面。如图所示:。



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

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

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

最后告诉大家一个不使用Asset来配置Icon的方法:直接在Info.plist下面这样写:



这个是通用的,可以直接设置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

改变iOS app的icon(iOS10.3)的更多相关文章

  1. 改变iOS app的icon(iOS10.3)

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

  2. 17.iOS App设置icon,启动图,App名称的方法

    icon:选择Assets-->AppIcon-->将各种尺寸的icon拖拽到相应的框中. APP名称:选择info-->Bundle name,修改APP名字. 启动图: 首先点击 ...

  3. 在iOS App的图标上显示版本信息

    最近读到一篇文章(http://www.merowing.info/2013/03/overlaying-application-version-on-top-of-your-icon/)介绍了一种非 ...

  4. [摘抄]iOS App icon、启动页、图标规范

    以下内容都是我在做App时通过自己的经验和精品的分析得来的,希望会帮助到你.但是有时个别情况也要个别分析,要活学活用. 一. App  Icon 在设计iOS App Icon时,设计师不需要切圆角, ...

  5. Asset Catalog Help (五)---Migrating an iOS App Icon Set or Launch Image Set

    Migrating an iOS App Icon Set or Launch Image Set Simplify image management by moving existing app i ...

  6. Asset Catalog Help (四)---Adding an iOS App Icon Set or Launch Image Set

    Adding an iOS App Icon Set or Launch Image Set Organize different resolutions of your app icons and ...

  7. iOS 在iphoneX上运行的app没有icon图标,在其他手机上有图标

    今天朋友问了一个问题,在iPhoneX上运行的app没有icon图标,在其他手机上有图标. 一开始我以为是没放iPhoneX的图标,后面朋友解决了,告诉了我原因,这里记录下吧: 原因: 图标格式问题, ...

  8. (转)在iOS中使用icon font

    http://ued.taobao.org/blog/?p=8579 在开发阿里数据iOS版客户端的时候,由于项目进度很紧,项目里的所有图标都是用最平常的背景图片方案来实现.而为了要兼容普通屏与Ret ...

  9. 在iOS中使用icon font

    博文转载至 http://www.cocoachina.com/industry/20131111/7327.html 在开发阿里数据iOS版客户端的时候,由于项目进度很紧,项目里的所有图标都是用最平 ...

随机推荐

  1. 阿里巴巴Java开发手册评述

    2016年底的时候阿里巴巴公开了其在内部使用的Java编程规范.随后进行了几次版本修订,目前的版本为v1.0.2版.下载地址可以在其官方社区-云栖社区https://yq.aliyun.com/art ...

  2. 连连看的原生JS实现

    那天闲来无事,便想找个小游戏来打发时间,后来便找到了连连看, 玩了一会儿感觉无聊,想到各位高手用JS做的各种小游戏,便想自己也来做一个,于是便有了这几天的成果. 代码是用 原生JS 实现的,只是用来学 ...

  3. 【openstack N版】——镜像服务glance

    一.openstack镜像服务glance 1.1 glance介绍 glance主要是由三部分组成 glance-api:接收云系统镜像的创建,删除,读取请求,类似nova-api,通过其他模块(g ...

  4. Angular2 路由问题修复 、求解

    Angular2 提供了比angular1 更为强大的路由功能,但是在具体使用路由过程中,可是出现了很多路由不按照预想的方式执行的问题.为了说明今天的问题,我特地新建了一个测试工程.欢迎交流. 首先介 ...

  5. ABP 学习汇总

    本文背景 公司最近规划的新框架准备基于ABP来搭建,自从在阳铭博客看到ABP框架的介绍后,就一直持续关注着,但还没真正在实际项目中直接使用ABP,只是自己做了一些学习和Demo.ABP所用到的一些新技 ...

  6. 百度网盘免费扩容 免费扩容到2048G

    您可以用手机端扩容 http://yun.baidu.com/1t 免费扩容到2048G

  7. Android中使用Handler以及CountDownTimer实现包含倒计时的闪屏页面

    上一篇博文<Android中Handler使用浅析>通过实现倒计时闪屏页面的制作引出了Handler的使用方法以及实现原理,博文末尾也提到了实现过程中的Bug,有兴趣的朋友可以点击链接回去 ...

  8. JavaScript学习12 JS中定义对象的几种方式【转】

    avaScript学习12 JS中定义对象的几种方式 转自:  http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. ...

  9. android sdk tools 一览

    ANDROID SDK ADKROID SDK的工具划分为两部分,一部分是SDK tools,与平台无关,另一部分是Platform tools支持最新的安卓平台   SDK tools有 SDK m ...

  10. 1638: [Usaco2007 Mar]Cow Traffic 奶牛交通

    1638: [Usaco2007 Mar]Cow Traffic 奶牛交通 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 618  Solved: 217 ...