iOS:动态更换App Icon

帮助类

// MZAppIconService.h
#import 

NS_ASSUME_NONNULL_BEGIN

@interface MZAppIconService : NSObject

+ (instancetype)shareService;

/// 更换为指定name的icon
/// @param iconName 新cicon的名字
/// @param showAlert 替换完成是否提示
/// @param complete 结果回调
- (void)changeIconWithName:(NSString *)iconName showAlert:(BOOL)showAlert complete:(void(^)(BOOL result, NSString *msg))complete;

@end

NS_ASSUME_NONNULL_END


// MZAppIconService.m
#import "MZAppIconService.h"

#import 

@implementation MZAppIconService

+ (instancetype)shareService {
    static MZAppIconService *service;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        service = [[self alloc] init];
    });
    return service;
}

- (void)changeIconWithName:(NSString *)iconName showAlert:(BOOL)showAlert complete:(nonnull void (^)(BOOL, NSString * _Nonnull))complete {
    // 动态更换App Icon是从10.3才有的功能
    if (@available(iOS 10.3, *)) {
        UIApplication *application = [UIApplication sharedApplication];
        // 判断是否支持更换
        if ([application supportsAlternateIcons]) {
            // 如果不需要展示更换成功的弹框,就屏蔽掉
            if (!showAlert) { [self clearAlert]; }
            // 执行更换
            [application setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
                // 更换的结果回调
                if (error) {
                    complete(NO, error.localizedDescription);
                } else {
                    complete(YES, @"更换App Icon成功");
                }
            }];
        }
    } else {
        // 如果系统版本过低
        complete(NO, @"系统版本过低,不支持App Icon的替换");
    }
}

- (void)clearAlert {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method presentM = class_getInstanceMethod([UIViewController class], @selector(presentViewController:animated:completion:));
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        Method presentSwizzlingM = class_getInstanceMethod([UIViewController class], @selector(mz_avoidAlertForchangeAppIcon:animated:completion:));
#pragma clang diagnostic pop
        method_exchangeImplementations(presentM, presentSwizzlingM);
    });
}

@end


@implementation UIViewController (MZChangeIcon)

- (void)mz_avoidAlertForchangeAppIcon:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
    
    if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
        
        UIAlertController *alertController = (UIAlertController *)viewControllerToPresent;
        if (alertController.title == nil && alertController.message == nil) {
            return;
        } else {
            [self mz_avoidAlertForchangeAppIcon:viewControllerToPresent animated:flag completion:completion];
            return;
        }
    }
    
    [self mz_avoidAlertForchangeAppIcon:viewControllerToPresent animated:flag completion:completion];
}

@end

需要在工程的info.plist里面配置:

CFBundleIcons

    CFBundleAlternateIcons
    
        IconApp
        
            CFBundleIconFiles
            
                IconApp20x20
                IconApp29x29
                IconApp40x40
                IconApp57x57
                IconApp60x60
                IconApp72x72
                IconApp76x76
                IconApp83.5x83.5
                IconSmall50x50
            
        
        IconAppOrigin
        
    
    CFBundlePrimaryIcon
    
        CFBundleIconFiles
        
            AppIcon
        
        UIPrerenderedIcon
        
    

  • iOS:动态更换App Icon_第1张图片
    图示

使用

- (IBAction)onClick:(UIButton *)btn {
    
    // 其中,`IconAppOrigin`和`IconApp`是info.plist的key
    NSString *iconName = btn.selected ? @"IconAppOrigin" : @"IconApp";
    [[MZAppIconService shareService] changeIconWithName:iconName showAlert:NO complete:^(BOOL result, NSString * _Nonnull msg) {
        NSLog(@"%d=====%@", result, msg);
    }];
    btn.selected = !btn.selected;
}

你可能感兴趣的:(iOS:动态更换App Icon)