上篇文章咱们详细查看了更换App图标的使用方法,并作了个小Demo。尽管当前咱们能够实现动态更换App图标了,可是每次更换图标时,苹果官方给加的“友好提示”对用户以及开发者都不是那么“友好“。官方并无给出能够不弹框的方法,毕竟App图标对于苹果来讲是一个很重要的审核部分,若是任由开发者在上架后不提示用户而随意修改图标,会形成很差的用户体验,因此苹果会在使用此API时弹框告知用户该App图标已修改(我的猜测)。git
不过今天咱们想谈谈如何突破这个弹框限制(毕竟开发者也不是傻,不会胡乱更换图标的是否是🤣)。github
Demo地址:github.com/maybeisyi/C…objective-c
本篇文章对应工程为:DynamicAppIcon(二)spa
Demo中能够看到,如今咱们能够作到不弹框直接修改App图标。实现该功能后,某些有意思的小功能就能有良好的用户体验了:白天/夜间模式切换,在切换App主色调同时切换App图标。code
下面将详细讲解如何"突破"苹果的限制。cdn
查看原Demo中的弹框,此弹框与UIAlertController长的却是挺像的。让咱们来剖析下这个弹框:blog
能够看到弹框就是私有类_UIAlertControllerView
,让咱们再对比下系统的UIAlertController:开发
因此更换App时的弹框就是UIAlertController,只不过上面的控件不太同样罢了。(其实咱们也能作到在UIAlertController上添加任意控件)get
既然知道了弹框是UIAlertController,那么咱们天然而然想到,该弹框是由ViewController经过presentViewController:animated:completion:
方法弹出。那么咱们就能够经过Method swizzling hook该弹框,不让其进行弹出便可:it
#import "UIViewController+Present.h" #import@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 复制代码
这段代码交换了UIViewController
的presentViewController:animated:completion:
方法。经过打印UIAlertController的特征,咱们能够发现,更换App图标时的弹框是没有title与message的,可是咱们通常使用的UIAlertController都是带title、message的,毕竟不会弹个空白的框给用户玩。
因此该方法中经过判断title与message来捕捉更换App图标时的弹框,并直接return便可。
其实关于界面上的东西,利用动态特性没有什么是不能作的,苹果既然公开了动态API,咱们就能够经过动态方法去了解甚至改造咱们想要的东西,如系统控件如何实现等。苹果的”规范“在应用层面实际上是没法阻挡开发者步伐的,固然动态特性也不可以滥用(如私有方法),毕竟审核人员才是爸爸。
尽管目前实现了在用户无感的状况下替换App图标,可是可替换的图标仍是必须预先放入工程中,而且要在Info.plist内指定。这很大程度上限制了更换图标的动态性:好比咱们某天想要推出一款新主题以及对应的App图标,可是新的App图标并无预先放入工程的main bundle中,也没有在Info.plist中进行指定,因此咱们在不上架新版本的状况下,没法推出该新App图标,所以有这了第三篇文章。
第三篇文章:《iOS动态更换App图标(三):动态下载App图标进行更换》短时间内应该没法实现,具体缘由会在文章中说明。