动态改变APP图标
一、iOS动态更换App图标(一):基础使用
该功能应用的场景
1、白天/夜间模式切换,在切换App主色调同时切换App图标。
2、各类皮肤主题(淘宝就可换肤),附带App图标一块更换。
3、利用App图标表达某种特定功能,如Demo中的,提示当前天气。
4、图标促销提示,如淘宝京东特定节日:11.11、6.18,提前更换App图标。
当然该功能(API)当前只支持iOS10.3以上的系统,所以只能当做一项附加功能来进行使用。下面将详细讲解下如何使用代码来实现此功能。
API方法
@interface UIApplication (UIAlternateApplicationIcons)
// 如果为NO,表示当前进程不支持替换图标
@property (readonly, nonatomic) BOOL supportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
// 传入nil代表使用主图标. 完成后的操作将会在任意的后台队列中异步执行; 如果需要更改UI,请确保在主队列中执行.
- (void)setAlternateIconName:(nullable NSString *)alternateIconName completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
// 如果alternateIconName为nil,则代表当前使用的是主图标.
@property (nullable, readonly, nonatomic) NSString *alternateIconName NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
@end
- (void)setAppIconWithName:(NSString *)iconName {
if (![[UIApplication sharedApplication] supportsAlternateIcons]) {
return;
}
if ([iconName isEqualToString:@""]) {
iconName = nil;
}
[[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"更换app图标发生错误了 : %@",error);
}
}];
}
配置文件(Info.plist)

当然也要拖入对应的App图标:

不过这里我们好像还少配置了App主图标,也就是正常情况下我们的图标。按照文档所说,我们需要在CFBundleIcons里面配置CFBundlePrimaryIcon这个主图标对应的内容,但是实际上,我们还是按照老方法,在Assets.xcassets中配置AppIcon,对应尺寸填上对应图片即可。为什么这样子就可以配置主图标呢?让我们来看看某知名电商的ipa(在AppStore上下载的包)内的Info.plist(位于Payload/XXXXXX/Info.plist):

拦截弹框
既然知道了弹框是UIAlertController,那么我们自然而然想到,该弹框是由ViewController通过presentViewController:animated:completion:方法弹出。那么我们就可以通过Method swizzling hook该弹框,不让其进行弹出即可:
#import "UIViewController+Present.h"
#import <objc/runtime.h> @implementation UIViewController (Present) + (void)load { static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method presentM = class_getInstanceMethod(self.class, @selector(presentViewController:animated:completion:));
Method presentSwizzlingM = class_getInstanceMethod(self.class, @selector(dy_presentViewController:animated:completion:)); method_exchangeImplementations(presentM, presentSwizzlingM);
});
} - (void)dy_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion { if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
NSLog(@"title : %@",((UIAlertController *)viewControllerToPresent).title);
NSLog(@"message : %@",((UIAlertController *)viewControllerToPresent).message); UIAlertController *alertController = (UIAlertController *)viewControllerToPresent;
if (alertController.title == nil && alertController.message == nil) {
return;
} else {
[self dy_presentViewController:viewControllerToPresent animated:flag completion:completion];
return;
}
} [self dy_presentViewController:viewControllerToPresent animated:flag completion:completion];
} @end
或者
#import "ViewController.h"
#import <objc/runtime.h> // 利用runtime来替换展现弹出框的方法
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method presentM = class_getInstanceMethod(self.class, @selector(presentViewController:animated:completion:));
Method presentSwizzlingM = class_getInstanceMethod(self.class, @selector(ox_presentViewController:animated:completion:));
// 交换方法实现
method_exchangeImplementations(presentM, presentSwizzlingM);
}); // 自己的替换展示弹出框的方法
- (void)ox_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion { if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
NSLog(@"title : %@",((UIAlertController *)viewControllerToPresent).title);
NSLog(@"message : %@",((UIAlertController *)viewControllerToPresent).message); // 换图标时的提示框的title和message都是nil,由此可特殊处理
UIAlertController *alertController = (UIAlertController *)viewControllerToPresent;
if (alertController.title == nil && alertController.message == nil) {// 是换图标的提示
return;
} else {// 其他提示还是正常处理
[self ox_presentViewController:viewControllerToPresent animated:flag completion:completion];
return;
}
} [self ox_presentViewController:viewControllerToPresent animated:flag completion:completion];
}
这段代码交换了UIViewController的presentViewController:animated:completion:方法。通过打印UIAlertController的特征,我们可以发现,更换App图标时的弹框是没有title与message的,但是我们一般使用的UIAlertController都是带title、message的,毕竟不会弹个空白的框给用户玩。
所以该方法中通过判断title与message来捕捉更换App图标时的弹框,并直接return即可。
《iOS动态更换App图标(三):动态下载App图标进行更换》短期内应该无法实现
动态改变APP图标的更多相关文章
- 【转】【iOS】动态更换App图标
原文网址:http://www.cocoachina.com/ios/20170619/19557.html 前言 动态更换App图标这件事,在用户里总是存在需求的:有些用户喜欢“美化”自己的手机.至 ...
- Android动态改变App在Launcher里面的icon
如果呆萌的产品童鞋让你动态更换App在Launcher里面的Icon,你怎么回答他,下文就提出一种实现该效果的方法. 原理1--activity-alias 在AndroidMainifest中,有两 ...
- iOS 10.3+ 动态修改 App 图标
支持系统: iOS 10.3+ tvOS 10.2+ Apple 官方文档 官方 API: @interface UIApplication (UIAlternateApplicationIcons) ...
- 动态改变actionbar上menu的图标
工作中遇到了一个需求是,在滚动的时候让actionbar上的图标进行变色.实现后在这里总结下思路. 一.先在主题中定义好Actionbar的style <style name="App ...
- 如何在运行时改变App的图标
在你完成应用程序的beta版本后,最后会有些人去帮你测试,使你去完善应用程序……或者会有投资青睐.但是如果测试人员有一种简单地方式去检查构建版本的应用程序会不会有帮助呢? 这个教程将会向你展示这些,向 ...
- android 动态改变listview的内容
本文模拟:点击一个按钮,为已有的listview添加一行数据 <?xml version="1.0" encoding="utf-8"?> < ...
- Windows Phone 动态改变ListBox样式
使用ListBox时通常会借助ItemTemplate帮助我们实现更复杂多样的样式显示,体现了Xaml的灵活.如何动态改变变ListBox的样式,实现类似电脑资源管理器中列表显示和图标显示形式的替换. ...
- WPF动态改变主题颜色
原文:WPF动态改变主题颜色 国内的WPF技术先行者周银辉曾介绍过如何动态改变应用程序的主题样式,今天我们来介绍一种轻量级的改变界面风格的方式--动态改变主题色. 程序允许用户根据自己的喜好来对界面进 ...
- vue router 修改title(IOS 下动态改变title失效)
在ios下app 设置document.title = "titleName" 失效,原因是在IOS webview中网页标题只加载一次,动态改变是无效的. 在路由配置中添加 ...
随机推荐
- 【Algorithm | 链表】单链表“环”、“环的起点”、“环的长度”问题
参考资料 • Floyd判圈算法 { 链接 } • 单链表“环”.“环的起点”.环的长度”问题 { 链接 } 链表环的问题 一.判断链表有换 使用两个指针slow和fast.两个指针开始时均在头节点处 ...
- python全栈开发day27-网络编程
回顾:1.两个架构:C/S B/S(统一了应用的接口)2.同一个电脑两个py文件通信(文件)3.两个电脑通信---网线4.交换机的通信方式:广播.单播.组播5.arp协议:通过ip地址找到对应的m ...
- Codeforces Round #220 (Div. 2) D - Inna and Sequence
D - Inna and Sequence 线段数维护区间有几个没有被删除的数,利用线段树的二分找第几个数在哪里,然后模拟更新就好啦. #include<bits/stdc++.h> #d ...
- POJ2891 Strange Way to Express Integers 扩展欧几里德 中国剩余定理
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ2891 题意概括 给出k个同余方程组:x mod ai = ri.求x的最小正值.如果不存在这样的x, ...
- CSS 3. 文本|字体|背景|定位
1.文本属性和字体属性 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- Loogn.OrmLite文档
Getting Started 一. 引入Loogn.OrmLite PM> Install-Package Loogn.OrmLite 二.引入名称空间 using Loogn.OrmLite ...
- luogu P4688 [Ynoi2016]掉进兔子洞 bitset 莫队
题目链接 luogu P4688 [Ynoi2016]掉进兔子洞 题解 莫队维护bitset区间交个数 代码 // luogu-judger-enable-o2 #include<cmath&g ...
- 洛谷.4115.Qtree4/BZOJ.1095.[ZJOI2007]Hide捉迷藏(动态点分治 Heap)
题目链接 洛谷 SPOJ BZOJ1095(简化版) 将每次Solve的重心root连起来,会形成一个深度为logn的树,就叫它点分树吧.. 我们对每个root维护两个东西: 它管辖的子树中所有白点到 ...
- Codeforces.297C.Splitting the Uniqueness(构造)
题目链接 \(Description\) 给定一个长为n的序列A,求两个长为n的序列B,C,对任意的i满足B[i]+C[i]=A[i],且B,C序列分别至少有\(\lfloor\frac{2*n}{3 ...
- PHP算式验证码和汉字验证码的实现方法
在PHP网站开发中,验证码可以有效地保护我们的表单不被恶意提交,但是如果不使用算式验证码或者汉字验证码,仅仅使用简单的字母或者数字验证码,这样的验证码方案真的安全吗? 大家知道简单数字或者字母验证码很 ...