iOS替换应用图标

Xcode 集成多套测试 App 图标

实现多套 App 图标,依赖** Xcode13及以上版本**

Xcode13之前,如果要实现 iOS App 动态切换图标,需要在Info.plist中添加**CFBundleAlternatelcons**相关字段来声明对应的备用图标。如果要多套 App 图标,那么需要添加很多标签,不够直观和高效。
所以,在 Xcode 13 开始,可以通过项目的Assets.xcassets里创建 AppIcon 图标模板的形式,直观又方便管理图标。

如何给App添加多套图标

添加多套icon,跟平时添加应用icon一样,由于笔者没有完整的一整套icon,这里有部分icon没有添加上,实际开发中,必须添加所有尺寸的icon (注意,需要将每套的icon图片名称保持一致!)

在这里插入图片描述

然后将工程Build SettingsInclude all app icon assets改为 YES(注意,需要 Xcode 13 以上才有这个字段!)

在这里插入图片描述

如何验证是否配置多套图标成功了

编译后查看Product文件夹中的包体,或者Archive后查看包体中的 Info.plist文件下Icon files (iOS 5) 配置下是否有 CFBundleAlternateIcons 对应的多套图标的名字,如下图:

在这里插入图片描述

如何通过代码动态替换应用图标

Objective-C 代码动态替换应用图标如下:

注意:动态替换图标是在iOS 10.3以上才可以使用,所以要注意判断系统版本

setAlternateIconName: 如果参数传nil可以重置为应用原始图标


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    
    [self changeAppIconWithName:@"AppIcon1"];
    
    
}


- (void)changeAppIconWithName:(NSString *)iconName {
    
    if (@available(iOS 10.3, *)) {
        
        if (![[UIApplication sharedApplication] supportsAlternateIcons]) {
            return;
        }
        
        if ([iconName isEqualToString:@""]) {
            //传nil可重置为原始icon
            iconName = nil;
        }
        
        [[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
            if (error) {
                NSLog(@"更换app图标发生错误了 : %@",error);
            }else{
                NSLog(@"更换成功");
            }
        }];
        
    } else {
        NSLog(@"版本太低了");
    }
    
}

Swift代码操作如下:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        self.changeAppIcon(iconName: "AppIcon1")
    }
    
    func changeAppIcon(iconName: String?) {
        if #available(iOS 10.3, *) {
            
            if UIApplication.shared.supportsAlternateIcons == false {
                
                return;
            }
            
            //iconName 如果传nil 可以重置为原始icon
            UIApplication.shared.setAlternateIconName(iconName) { error in
                
                if error != nil {
                    print("更换app图标发生错误了" + "\(error.debugDescription)")
                } else {
                    print("替换icon成功")
                }
            }
            
        } else {
            
            print("系统版本太低了")
            
        }
        
    }

提示动态替换图标成功如下:

在这里插入图片描述

如何无感替换应用图标

在运行时runtime下用Method swizzling对弹框方法进行捕捉替换,可以在用户无感的情况下替换图标

建一个UIViewControllerCategory,结合+ (void)load 自动执行加载 Method swizzling 方法替换

Objective-C具体代码操作如下:

#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]]) {
        
        UIAlertController *alertController = (UIAlertController*)viewControllerToPresent;
        
        if (alertController.title == nil && alertController.message == nil) {
            
            NSLog(@"替换图标操作");
            return;
            
        } else {
            
            [self dy_presentViewController:viewControllerToPresent animated:flag completion:completion];
            return;
            
        }
        
    }
    
    [self dy_presentViewController:viewControllerToPresent animated:flag completion:completion];
    
}

@end

Swift代码操作如下:

写一个UIViewController扩展方法

extension UIViewController {
    
    public class func initializeMethod() {
        
        let presentSelector = #selector(UIViewController.present(_:animated:completion:))
        let swizzledPresentSelector = #selector(UIViewController.customPresent(_:animated:completion:))
        
        let presentMethod = class_getInstanceMethod(self, presentSelector)
        let swizzledPresentMethod = class_getInstanceMethod(self, swizzledPresentSelector)
        
        let didAddPresentMethod: Bool = class_addMethod(self, presentSelector, method_getImplementation(swizzledPresentMethod!), method_getTypeEncoding(presentMethod!))
        
        if didAddPresentMethod {
            class_replaceMethod(self, swizzledPresentSelector, method_getImplementation(presentMethod!), method_getTypeEncoding(presentMethod!))
        } else {
            method_exchangeImplementations(presentMethod!, swizzledPresentMethod!)
        }
    }
    
    
    @objc func customPresent(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        
        if viewControllerToPresent is UIAlertController {
            
            
            if let alertController = viewControllerToPresent as? UIAlertController {
                
                if alertController.title == nil && alertController.message == nil {
                    
                    print("替换图标操作")
                    return
                } else {
                    
                    self .customPresent(viewControllerToPresent, animated: flag, completion: completion)
                    return
                }
            }
            
        }
        
        self .customPresent(viewControllerToPresent, animated: flag, completion: completion)
        
    }
    
}

在应用启动方法中执行 Method swizzling初始化方法

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        UIViewController.initializeMethod()
        
        return true
    }

以上是笔者在工作中遇到的替换图标需求,实现后的简单总结,亲测有效!!!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值