整这东西整了一晚上,国内关于技术的文章实在是太不严谨了,小细节导致我走了很多弯路,最后在国外网站上找到的正确答案
参阅 https://www.hackingwithswift.com/example-code/uikit/how-to-change-your-app-icon-dynamically-with-setalternateiconname
准备材料
要替换的app图标文件(大小就按照普通的App尺寸来,iOS 有20x20,29x29,40x40,60x60)
像这样的一组图片,后面会用到
在开始之前,先看下怎么实现图标变化
在动态更换图标,用的方法是 UIApplication 的
func setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Void)? = nil)
其方法的说明是这样的
其中最主要的是就是 这个 alternateIconName
的 String 传的是什么,知道这个传的是什么就完活儿。这里不是 Assets.xcassets
中的名字,也不是项目目录中图片的名字。
这里的 String 应该是 在 Info.plist中定义的 可替换图标
的名字,具体看下面
1,拖动替换的app图标到项目中
把上面提到的图片放在项目目录中,而不是 Assets.xcassets
中!,这地方一定要注意;这组图片的目录结构无所谓,在文件夹中或根目录都无所谓。
原始图标还是正常的放在
Assets.xcassets
中,正常使用
2,配置Info.plist
我写这文章的时候用的是 xcode 8.3.3, Info.plist
显示的是这样的,我们要修改的就是最下面那个 Icon files
的内容
(这里说一点,其实,Icon files
这个名字只是个注释的名字,其真字段名并不是这个,你可以在 Info.plist
界面上右击 选择 Show Raw Key/Value
,就会看到下面的样子
显示原始字段名和值:
说下 CFBundleIcons
结构: 参阅官方文档 :关于CFBundleIcons 的说明
- CFBundleIcons //
有三个主分支,其它两个的子分支就不说了,自己看文档吧,这里主要说中间那个
- CFBundlePrimaryIcon //
程序主图标
- CFBundleAlternateIcons //
可替换图标,我们主要说这个,它的子分支如下
- 图标名称-1
- CFBundleIconFiles //
要替换的图标各尺寸集合
- item0
- item1
- item2
- …
- UIPrerenderedIcon //
是否需要高光显示图标
- CFBundleIconFiles //
- 图标名称-2
- CFBundleIconFiles //
要替换的图标各尺寸集合
- item0
- item1
- item2
- …
- UIPrerenderedIcon
- CFBundleIconFiles //
- 图标名称-1
- UINewsstandIcon
- CFBundlePrimaryIcon //
再给个图
也就是说,每个可替换的图标的内容都是固定的,就照着来就行。 CFBundleIconFiles
是个图片名称的数组,可以添加多个,系统会自动选择需要的图片大小,所以你把 20 29 40 60 的图片都放里面就好了。
最终的 Info.plist
是这样的,希望你能看明白,里面的 FullMoon
和 HalfMoon
就是两个图标集合了,使用的时候,就是用这两个名字。
FullMoon_20
, FullMoon_29
等等,就是图片原始名,直接指向项目目录中的图片,写的时候不要写 @2x
和 @3x
了,
在程序中实现代码就行了
上面的如果做好了,这里就只需要调用一下之前的那个方法
func setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Void)? = nil)
let application = UIApplication.shared
application.setAlternateIconName("FullMoon", completionHandler: { (error) in
// 写你需要做的东西
})
application.setAlternateIconName("HalfMoon", completionHandler: { (error) in
// 写你需要做的东西
})
如果想让图标回到原始图标,设为 nil 即可
application.setAlternateIconName( nil , completionHandler: { (error) in
// 写你需要做的东西
})
可能说的不是太清楚,有什么不太清楚的再留言问我吧