Xcode 集成多套测试 App 图标
实现多套 App 图标,依赖** Xcode13及以上版本** 。
在Xcode13之前,如果要实现 iOS App 动态切换图标,需要在Info.plist中添加**CFBundleAlternatelcons**相关字段来声明对应的备用图标。如果要多套 App 图标,那么需要添加很多标签,不够直观和高效。
所以,在 Xcode 13 开始,可以通过项目的Assets.xcassets里创建 AppIcon 图标模板的形式,直观又方便管理图标。
如何给App添加多套图标
添加多套icon,跟平时添加应用icon一样,由于笔者没有完整的一整套icon,这里有部分icon没有添加上,实际开发中,必须添加所有尺寸的icon (注意,需要将每套的icon图片名称保持一致!)
然后将工程Build Settings中 Include all app icon assets改为 YES。(注意,需要 Xcode 13 以上才有这个字段!)
如何验证是否配置多套图标成功了
编译后查看Product文件夹中的包体,或者Archive后查看包体中的 Info.plist文件下Icon files (iOS 5) 配置下是否有 CFBundleAlternateIcons 对应的多套图标的名字,如下图:
如何通过代码动态替换应用图标
注意:动态替换图标是在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(@"版本太低了");
}
}
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对弹框方法进行捕捉替换,可以在用户无感的情况下替换图标
建一个UIViewController的Category,结合+ (void)load 自动执行加载 Method swizzling 方法替换
#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
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
}
以上是笔者在工作中遇到的替换图标需求,实现后的简单总结,亲测有效!!!
原文地址:https://blog.csdn.net/Locationluqc/article/details/127680353
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_17665.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!