swift动态替换应用图标
2017-12-27 14:37
666 查看
近期需求中有一个需要动态替换应用图标的功能,查了下相关资料:在ios10.3之前是无法实现的,你只能提前发布拥有新应用图标的版本,来满足某个节日;节后,再发布一版,改回图标。从ios10.3开始,苹果提供了动态替换应用图标的API。至于api说明,请看苹果帮助,下面我们就按步骤实现这个功能。
1、准备好替换图标,我准备了春、夏、秋、冬四种替换图标,详见Demo。
2、在项目plist文件的根字典中添加如下:
即下图所示
3、在视图控制器中添加五个按钮:"春"用于替换春字图标,"夏"用于替换夏字图标, "秋"用于替换秋字图标, "冬"用于替换冬字图标,按钮"原始"用于恢复原始标, 点击实现如下:
4、运行程序,点击按钮,会出现如下alert, 你切到主屏幕界面会发现应用图标已替换。
5、对于每次替换图标就弹出个提示,我个人觉得不太爽,需要想办法去掉。替换原理是:因为alert是通过UIViewController的present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Swift.Void)? = nil)方法弹出的,我们只要修改该消息的实现,他就不会弹出了。这里就要用到OC的swizzling method技术,swift默认是静态绑定方法实现的,需要对想拥有动态消息特征的方法添加
@objc dynamic修饰符。这里只谈实现,至于OC的相关技术大家自行了解。
在视图控制器中添加如下三个方法:
//利用runtime指定方法实现
func runtimeRemoveAlert() -> Void {
if let presentM = class_getInstanceMethod(type(of: self), #selector(present(_:animated:completion:))),
let presentSwizzlingM = class_getInstanceMethod(type(of: self), #selector(temporary_present(_:animated:completion:))){
method_exchangeImplementations(presentM, presentSwizzlingM)
}
}
//利用runtime恢复方法实现
func runtimeResetAlert() -> Void {
if let presentM = class_getInstanceMethod(type(of: self), #selector(present(_:animated:completion:))),
let presentSwizzlingM = class_getInstanceMethod(type(of: self), #selector(temporary_present(_:animated:completion:))){
method_exchangeImplementations(presentM, presentSwizzlingM)
}
}
//在自己实现中特殊处理
@objc dynamic func temporary_present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Swift.Void)? = nil){
if viewControllerToPresent.isKind(of: UIAlertController.self) {
if let alertController = viewControllerToPresent as? UIAlertController{
//通过判断title和message都为nil,得知是替换icon触发的提示。
if alertController.title == nil && alertController.message == nil {
return;
}
}
}
self.temporary_present(viewControllerToPresent, animated: flag, completion: completion)
}
6、在视图控制器中如下调用:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.runtimeRemoveAlert()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.runtimeResetAlert()
}
7、为了验证对正常的alert展示没有影响,在视图控制器中添加“alert”按钮,对于点击处理如下:
@IBAction func alertClicked(_ sender: UIButton) {
let title = "title"
let msg = "message"
let cancelTitle = "cancel"
let okTitle = "ok"
let alertController = UIAlertController(title: title, message: msg, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel) { (action: UIAlertAction) in
print("cancel")
}
let okAction = UIAlertAction(title: okTitle, style: .default) { (action: UIAlertAction) in
print("ok")
}
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.present(alertController, animated: true) {
}
}
8、运行发现替换图标时,提示已不再出现;但是聪明的你会发现,这时completionHandler没被调用,因为他是前面展示的Alert后,点击OK按钮触发的。
工程下载地址https://github.com/qianlima210210/AlternateIconsDemo.git
1、准备好替换图标,我准备了春、夏、秋、冬四种替换图标,详见Demo。
2、在项目plist文件的根字典中添加如下:
<dict> <key>CFBundleIcons</key> <dict> <key>CFBundleAlternateIcons</key> <dict> <key>春</key> <dict> <key>CFBundleIconFiles</key> <array> <string>春Icon-Small-20</string> <string>春Icon-60</string> <string>春Icon-Small-29</string> <string>春Icon-Small-40</string> </array> <key>UIPrerenderedIcon</key> <false/> </dict> <key>夏</key> <dict> <key>CFBundleIconFiles</key> <array> <string>夏Icon-Small-20</string> <string>夏Icon-60</string> <string>夏Icon-Small-29</string> <string>夏Icon-Small-40</string> </array> <key>UIPrerenderedIcon</key> <false/> </dict> <key>秋</key> <dict> <key>CFBundleIconFiles</key> <array> <string>秋Icon-Small-20</string> <string>秋Icon-60</string> <string>秋Icon-Small-29</string> <string>秋Icon-Small-40</string> </array> <key>UIPrerenderedIcon</key> <false/> </dict> <key>冬</key> <dict> <key>CFBundleIconFiles</key> <array> <string>冬Icon-Small-20</string> <string>冬Icon-60</string> <string>冬Icon-Small-29</string> <string>冬Icon-Small-40</string> </array> <key>UIPrerenderedIcon</key> <false/> </dict> </dict> </dict>
即下图所示
3、在视图控制器中添加五个按钮:"春"用于替换春字图标,"夏"用于替换夏字图标, "秋"用于替换秋字图标, "冬"用于替换冬字图标,按钮"原始"用于恢复原始标, 点击实现如下:
/// 春天图标 @IBAction func 春Clicked(_ sender: UIButton) { if #available(iOS 10.3, *) { if UIApplication.shared.supportsAlternateIcons { print("替换前图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") //当前显示的是原始图标 UIApplication.shared.setAlternateIconName("春", completionHandler: { (error: Error?) in print("替换后图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") }) } } } /// 夏天图标 @IBAction func 夏Clicked(_ sender: UIButton) { if #available(iOS 10.3, *) { if UIApplication.shared.supportsAlternateIcons { print("替换前图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") //当前显示的是原始图标 UIApplication.shared.setAlternateIconName("夏", completionHandler: { (error: Error?) in print("替换后图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") }) } } } /// 秋天图标 @IBAction func 秋Clicked(_ sender: UIButton){ if #available(iOS 10.3, *) { if UIApplication.shared.supportsAlternateIcons { print("替换前图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") //当前显示的是原始图标 UIApplication.shared.setAlternateIconName("秋", completionHandler: { (error: Error?) in print("替换后图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") }) } } } /// 冬天图标 @IBAction func 冬Clicked(_ sender: UIButton){ if #available(iOS 10.3, *) { if UIApplication.shared.supportsAlternateIcons { print("替换前图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") //当前显示的是原始图标 UIApplication.shared.setAlternateIconName("冬", completionHandler: { (error: Error?) in print("替换后图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") }) } } } /// 原始图标 @IBAction func primaryClicked(_ sender: UIButton){ if #available(iOS 10.3, *) { if UIApplication.shared.supportsAlternateIcons { print("替换前图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") //当前显示的是原始图标 UIApplication.shared.setAlternateIconName(nil, completionHandler: { (error: Error?) in print("替换后图标:\(UIApplication.shared.alternateIconName ?? "原始图标")") }) } } }
4、运行程序,点击按钮,会出现如下alert, 你切到主屏幕界面会发现应用图标已替换。
5、对于每次替换图标就弹出个提示,我个人觉得不太爽,需要想办法去掉。替换原理是:因为alert是通过UIViewController的present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Swift.Void)? = nil)方法弹出的,我们只要修改该消息的实现,他就不会弹出了。这里就要用到OC的swizzling method技术,swift默认是静态绑定方法实现的,需要对想拥有动态消息特征的方法添加
@objc dynamic修饰符。这里只谈实现,至于OC的相关技术大家自行了解。
在视图控制器中添加如下三个方法:
//利用runtime指定方法实现
func runtimeRemoveAlert() -> Void {
if let presentM = class_getInstanceMethod(type(of: self), #selector(present(_:animated:completion:))),
let presentSwizzlingM = class_getInstanceMethod(type(of: self), #selector(temporary_present(_:animated:completion:))){
method_exchangeImplementations(presentM, presentSwizzlingM)
}
}
//利用runtime恢复方法实现
func runtimeResetAlert() -> Void {
if let presentM = class_getInstanceMethod(type(of: self), #selector(present(_:animated:completion:))),
let presentSwizzlingM = class_getInstanceMethod(type(of: self), #selector(temporary_present(_:animated:completion:))){
method_exchangeImplementations(presentM, presentSwizzlingM)
}
}
//在自己实现中特殊处理
@objc dynamic func temporary_present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Swift.Void)? = nil){
if viewControllerToPresent.isKind(of: UIAlertController.self) {
if let alertController = viewControllerToPresent as? UIAlertController{
//通过判断title和message都为nil,得知是替换icon触发的提示。
if alertController.title == nil && alertController.message == nil {
return;
}
}
}
self.temporary_present(viewControllerToPresent, animated: flag, completion: completion)
}
6、在视图控制器中如下调用:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.runtimeRemoveAlert()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.runtimeResetAlert()
}
7、为了验证对正常的alert展示没有影响,在视图控制器中添加“alert”按钮,对于点击处理如下:
@IBAction func alertClicked(_ sender: UIButton) {
let title = "title"
let msg = "message"
let cancelTitle = "cancel"
let okTitle = "ok"
let alertController = UIAlertController(title: title, message: msg, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel) { (action: UIAlertAction) in
print("cancel")
}
let okAction = UIAlertAction(title: okTitle, style: .default) { (action: UIAlertAction) in
print("ok")
}
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.present(alertController, animated: true) {
}
}
8、运行发现替换图标时,提示已不再出现;但是聪明的你会发现,这时completionHandler没被调用,因为他是前面展示的Alert后,点击OK按钮触发的。
工程下载地址https://github.com/qianlima210210/AlternateIconsDemo.git
相关文章推荐
- Gradle多渠道打包(动态设定App名称,应用图标,替换常量,更改包名,变更渠道)
- Gradle多渠道打包(动态设定App名称,应用图标,替换常量,更改包名,变更渠道)
- Gradle多渠道打包(动态设定App名称,应用图标,替换常量,更改包名,变更渠道)方法一
- 在Gradle中编译一次生成不同的版本,动态设定应用标题,应用图标,替换常量,andrioid gradle
- Androd动态替换应用图标
- 【Andrioid】在Gradle中编译一次生成不同的版本,动态设定应用标题,应用图标,替换常量
- Gradle编译生成不同的版本,动态设定应用标题 / 应用图标 / 替换常量
- Gradle多渠道打包(动态设定App名称,应用图标,替换常量,更改包名,变更渠道)
- Android系统 小米/三星/索尼 应用启动图标未读消息数(BadgeNumber)动态提醒
- iOS开发中动态更换应用图标
- Swift如何在应用中添加图标更换功能
- android Notification 图标动态替换
- App logo图标或内部icon的动态替换
- Android 主界面应用图标的动态修改
- swift 如何在IOS应用图标上添加消息数
- Salesforce hybrid app 使用ionic 命令轻松 替换应用图标(icon)和启动画面(splash)
- Android应用设置多个启动图标,动态列换应用图标
- 动态修改桌面应用图标
- swift在IOS应用图标上添加提醒个数的方法
- android 隐藏应用图标,用快捷方式做启动入口,实现伪动态改变图标