程序内动态修改appIcon+Method Swizzling
2018-09-03 本文已影响6人
西门淋雨
程序内动态修改appIcon
#import <UIKit/UIKit.h>
@interface ChangeAppIconVC : UIViewController
@end
#import "ChangeAppIconVC.h"
@interface ChangeAppIconVC ()
@end
@implementation ChangeAppIconVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = [UIColor lightGrayColor];
[btn setTitle:@"换新的icon" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(changeIocn:) forControlEvents:UIControlEventTouchUpInside];
btn.frame = CGRectMake((CGRectGetWidth(self.view.frame)-200)*0.5, 100, 200, 30);
btn.tag = 100;
btn.titleLabel.font = [UIFont systemFontOfSize:15];
[self.view addSubview:btn];
UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
btn2.backgroundColor = [UIColor lightGrayColor];
[btn2 setTitle:@"换原来的icon" forState:UIControlStateNormal];
[btn2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn2 addTarget:self action:@selector(changeIocn:) forControlEvents:UIControlEventTouchUpInside];
btn2.frame = CGRectMake((CGRectGetWidth(self.view.frame)-200)*0.5, 200, 200, 30);
btn2.tag = 200;
btn2.titleLabel.font = [UIFont systemFontOfSize:15];
[self.view addSubview:btn2];
}
- (void)changeIocn:(UIButton *)sender{
if (sender.tag == 100) {
[self changeAppIconWithName:@"DYICON"];
}else{
[self changeAppIconWithName:@""];
}
}
- (void)changeAppIconWithName:(NSString *)iconName {
if (@available(iOS 10.3, *)) {
if (![[UIApplication sharedApplication] supportsAlternateIcons]) {
return;
}
if ([iconName isEqualToString:@""]) {
iconName = nil;
}
[[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"更换app图标发生错误了 : %@",error);
}
}];
} else {
UIAlertController *myAlertCon = [UIAlertController alertControllerWithTitle:@"提示" message:@"支持10.3以及以上版本" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[myAlertCon addAction:okAction];
[self presentViewController:myAlertCon animated:YES completion:nil];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
然后需要配置相关的图片:
1.默认的图片:
默认icon2.新增图片:
新增icon3.plist文件的配置,主要的是3,1和2 是默认就有的,不需要做修改。“DYICON”即要替换的新的icon 的图片集合。
plist配置上述代码就可以程序内替换图片了,相关的方法要求10.3以及以上。但是每次替换icon后都会弹框提示,不是很友好,可以用runtime去掉弹框。
#import <UIKit/UIKit.h>
@interface UIViewController (HideAlert)
@end
#import "UIViewController+HideAlert.h"
#import <objc/runtime.h>
@implementation UIViewController (HideAlert)
+ (void)load{
Method originalMethod = class_getInstanceMethod([self class], @selector(presentViewController:animated:completion:));
Method swizzlingMethod = class_getInstanceMethod([self class], @selector(swizzlingPresentViewController:animated:completion:));
BOOL didAddMethod = class_addMethod([self class], @selector(presentViewController:animated:completion:), method_getImplementation(swizzlingMethod), method_getTypeEncoding(swizzlingMethod));
if (didAddMethod) {
class_replaceMethod([self class], @selector(swizzlingPresentViewController:animated:completion:), method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}else{
method_exchangeImplementations(originalMethod, swizzlingMethod);
}
}
- (void)swizzlingPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion{
if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
UIAlertController *alertCon = (UIAlertController *)viewControllerToPresent;
if (alertCon.title == nil && alertCon.message == nil) {
UIAlertController *myAlertCon = [UIAlertController alertControllerWithTitle:@"提示" message:@"图标已替换" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}];
[myAlertCon addAction:okAction];
//这里会重新走swizzlingPresentViewController方法,然后alertCon.title != nil && alertCon.message != nil,然后执行swizzlingPresentViewController方法,其实是走的系统的presentViewController方法,方法结束。
// [self presentViewController:myAlertCon animated:YES completion:nil];
//如果调用这个方法则直接走的是系统的presentViewController的方法,然后方法结束
[self swizzlingPresentViewController:myAlertCon animated:YES completion:nil];
return;
}
}
[self swizzlingPresentViewController:viewControllerToPresent animated:flag completion:completion];
}
@end