程序内动态修改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.默认的图片:
默认icon
2.新增图片:
新增icon
3.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

git Demo地址

上一篇下一篇

猜你喜欢

热点阅读