这是我参与更文挑战的第14天,活动详情查看: 更文挑战
这个功能你们发现了吗?
不知道有没有在苹果手机上使用GitHub官方App的朋友们,你们有没有发现这样一个功能:
在这个App的设置里面,可以更换App的应用图标。
另外有个叫Cuto的壁纸App也有这个功能。(吐槽:Cuto需要是Vip用户才能使用这个功能,其实真的是很普通的代码很普通的Api呀)。
看到这个功能的时候,我当时就震惊了,这是用的哪门子hook技术?
然后感到兴趣的我屁颠屁颠的跑去查文档一看:iOS 10.3 加入了了更换应用图标的新功能,开发者可以为应用提供多个应用图标选择。
害!原来都是系统Api可以操作了,而且还是在iOS10.3之后,只能怪自己少见多怪。话不多说,撸起代码原地走起!
配置与使用
-
- 首先选取好图片素材,切好图片,重命名。
-
- 在info.plist文件中进行配置。
plist文件配置,添加Icon files (iOS 5)类型为Dictionary。
注意: 点开Icon files (iOS 5),里面有Primary Icon,Newsstand Icon两个key,Primary Icon 里面的图片为AppIcon默认图片。不用去管这个地方。
Icon files (iOS 5)里面创建一个CFBundleAlternateIcons,类型为Dictionary。
这个地方配置起来比较复杂,我直接上info.plist中的xml便于理解,直接将以下代码CV到info.plist中的源码中即可。
<key>LSApplicationCategoryType</key>
<string></string>
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string></string>
</array>
</dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>blackDuck</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>blackDuck-20</string>
<string>blackDuck-29</string>
<string>blackDuck-40</string>
<string>blackDuck-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>blackSeele</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>blackSeele-20</string>
<string>blackSeele-29</string>
<string>blackSeele-40</string>
<string>blackSeele-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>flowerWeddingRita</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>flowerWeddingRita-20</string>
<string>flowerWeddingRita-29</string>
<string>flowerWeddingRita-40</string>
<string>flowerWeddingRita-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>FlowerWeddingSakura</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>FlowerWeddingSakura-20</string>
<string>FlowerWeddingSakura-29</string>
<string>FlowerWeddingSakura-40</string>
<string>FlowerWeddingSakura-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>fuHua</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>fuHua-20</string>
<string>fuHua-29</string>
<string>fuHua-40</string>
<string>fuHua-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>grandmother</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>grandmother-20</string>
<string>grandmother-29</string>
<string>grandmother-40</string>
<string>grandmother-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>himeko</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>himeko-20</string>
<string>himeko-29</string>
<string>himeko-40</string>
<string>himeko-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>iceDuck</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>iceDuck-20</string>
<string>iceDuck-29</string>
<string>iceDuck-40</string>
<string>iceDuck-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>whiteSeele</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>whiteSeele-20</string>
<string>whiteSeele-29</string>
<string>whiteSeele-40</string>
<string>whiteSeele-60</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
</dict>
复制代码
-
- 这里我通过tableView点击进行AppIcon切换,逻辑简单,直接上代码了。
import UIKit
class ViewController: UIViewController {
let sizeString = "-60"
lazy var dataSource: [(String, String)] = [(title: "姬子", imageName: "himeko"),
(title: "白希", imageName: "whiteSeele"),
(title: "花嫁丽塔", imageName: "flowerWeddingRita"),
(title: "赤鸢仙人", imageName: "fuHua"),
(title: "黑希", imageName: "blackSeele"),
(title: "黑鸭", imageName: "blackDuck"),
(title: "花嫁桜", imageName: "FlowerWeddingSakura"),
(title: "理律", imageName: "iceDuck"),
(title: "岳母", imageName: "grandmother"),
]
private lazy var tableView: UITableView = {
let tableView = UITableView(frame: view.frame, style: .plain)
tableView.delegate = self
tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "TableViewCell")
tableView.tableFooterView = UIView(frame: CGRect.zero)
tableView.rowHeight = 66
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
setUpUI()
}
private func setUpUI() {
view.backgroundColor = .white
title = "更换AppIcon"
view.addSubview(tableView)
}
@objc
private func changeAppIcon(iconName: String) {
let app = UIApplication.shared
if app.supportsAlternateIcons {
app.setAlternateIconName(iconName, completionHandler: { (error) in
if error != nil {
print("error => \(String(describing: error?.localizedDescription))")
}else {
print("Done")
}
})
}
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath)
cell.textLabel?.text = dataSource[indexPath.row].0
cell.imageView?.image = UIImage(named: dataSource[indexPath.row].1 + sizeString)
return cell
}
}
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
let iconName = dataSource[indexPath.row].1
changeAppIcon(iconName: iconName)
}
}
复制代码
其核心Api是UIApplication.shared的以下方法:
// Pass `nil` to use the primary application icon. The completion handler will be invoked asynchronously on an arbitrary background queue; be sure to dispatch back to the main queue before doing any further UI work.
@available(iOS 10.3, *)
open func setAlternateIconName(_ alternateIconName: String?, completionHandler: ((Error?) -> Void)? = nil)
复制代码
好了,说实话我搞切图和重命名都比写代码累!!!
最后来一张效果图
你Get√到这个技巧了吗?是不是可以一顿操作猛如虎,隔壁就眼馋了?
Github资源地址:
考虑到这个地方的info.plist文件的配置比较复杂,目前正在整理代码,完成后会附上工程链接,请大家稍安勿躁。
思考:为何很多App不没有集成更换App图标的功能呢??
简单的配置,简单的Api,编写起来基本不存在任何技术难点,不过你可以看见市场上的App很少集成这个功能?
App应用图标更新的勤快如淘宝,也不过是在618、双11改改底色与副标题,也少会去动那个淘
字,从产品的角度看,App应用图标,是用户点击的入口,需要有一定的辨识度与品牌效应。
比如你使用某个App,觉得它特别好,想推荐给身边的人,一个设计鲜明、变更不大的App图标才是最关键,反之,如果一个App图标都经常更换,又有谁记住它呢?
这只是我的一点思考,大伙觉得呢?
明日继续
端午节最后一天,大家都好好休息了吗?明天就要上班啦,大家加油!
另外,我不当舰长好多年!