动态更新App的图标(AppIcon)

序言

        随着时代的进步,人的生活多元化。一些公司的 App 也随着人的生活改变而进行适和情景的变化。比如,本公司的 App 在四月时是本公司成立 4 周年的生日,那就想在本公司 AppIcon 上添加一个圣诞帽。第一种方法: 在 App 的工程中,替换原始的 AppIcon ,再提交 AppStore 进行审核。这种方法不说麻烦,而且耗费时间长。第二种:在 App 中动态更新 AppIcon 。 这种方法直接、快速、适合即时应用。


1、本博客介绍方法实现的效果图如下

效果图


2、 重点知识点的介绍

@interface UIApplication (UIAlternateApplicationIcons)
// If false, alternate icons are not supported for the current process.
@property (readonly, nonatomic) BOOL supportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));

// Pass `nil` to use the primary application icon. The completion handler will be invoked asynchronously on an arbitrary background queue; be sure to dispatch back to the main queue before doing any further UI work.
- (void)setAlternateIconName:(nullable NSString *)alternateIconName completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));

// If `nil`, the primary application icon is being used.
@property (nullable, readonly, nonatomic) NSString *alternateIconName NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
@end

1 / supportsAlternateIcons 函数

      该函数是判断设备是否支持备用 AppIcon 的功能。该功能的使用条件是设备的系统必须是 iOS 10.3 以上的版本。

2 / alternateIconName 参数

      该参数是一个只读属性的参数,如果该参数为 nil 时,那App 就会使用默认的AppIcon 。否则,App 使用的是备用AppIcon ,那么 alternateIconName 获得的结果就是App 正在使用的备用AppIcon的名子。

3 / setAlternateIconName: completionHandler: 函数

      该函数是执行AppIcon 图标替换的功能。在进行替换时 App 的系统会弹出一个提示让你确定是否变更AppIcon 。如果,要自动变更AppIcon ,那么这个提示就不能出现。对于如何去掉这个提示,后面介绍。


3、使用备用AppIcon需要在工程的 info.plist 文件中进行配置,配置如下:

工程配置

1、添加流程
  • 我们在工程的 Info.plist 文件中添加 Icon files(iOS 5)key 。该 key 的类型(Type)为 Dictionary
  • Icon files(iOS 5) 对应的字典,包含 2 个对象分别是: Primary IconNewsstand Icon。 这两个对象的类型也是 * Dictionary*
  • 我们要使用备用的AppIcon ,那么我们就要在 Icon files(iOS 5) 对应的字典中,添加一个对象 CFBundleAlternateIcons 对象,该对象的类型是字典(Dictionary)。
  • 我们在CFBundleAlternateIcons 对象中添加备用*AppIcon 的图像对象。如上图 Icon1Icon2 所示,这两个对象的类型也是字典。
  • 我们要在添加的AppIcon对象中在添加一个 CFBundleIconFiles 的对象,该对象的类型是数组(Array)。
  • CFBundleIconFiles 的对象中添加AppIcon 的图像文件名字为元素,该元素的类型是 String,以便后期使用。
2、参数介绍
  • Primary Icon  是默认 AppIcon 的对象。该对象包含 *Icon already includes gloss effectsIcon files 两个对象。 *Icon already includes gloss effects 是一个布尔类型,它表示AppIcon 是否是高光状态。Icon files 是一个数组对象,它包含默认的AppIcons 的文件名字对象,对象类型是字符串(String)。
  • CFBundleAlternateIcons   备用AppIcon 可能有好几个,那么CFBundleAlternateIcons 包含的对象就不只一个。我们介绍其中一个例如 Icon1 包含 CFBundleIconFiles 一个存放AppIcon 图像的数组。数组内是各个AppIcon 文件的名字。
  • Newsstand Icon    这是报刊类 Newsstand App 的图标设置。该对象包含 Binding edgeIcon filesBinding type 三个对象。Binding edge 是一个字符串对象,它的作用是设置Newsstand Icon 的位置,可选类型有 leftrightbottomIcon files 是一个数组对象,它里面存放图像的文件名字。Binding type 是设置Newsstand Icon 归属的类型,类型可选有 Magazine*Newspaper


4、 核心代码

#pragma mark Change 'AppIcon'
-(void) changeAppIcon:(NSString *) iconName {
    // TODO: Get the App itself
    UIApplication * application = [UIApplication sharedApplication];
    // TODO: Determine whether the device supports' AlternateIcons'
    /**
     *  AlternateIcons : 扩展备用图标。
     *  使用条件: ios10.3 以上的设备
     */
    if ([application supportsAlternateIcons]) {
        // Change the 'AppIcon'
        [application setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
            // Change the abnormal result of 'AppIcon'
            NSLog(@"%@",error);
        }];
    }
}

App 程序中调用上面的函数,就可实现AppIcon的变更。注意,当你调用时,系统会弹出一个提示,让你确定进行AppIcon 的变更操作,确定后AppIcon 才会替换。如下所示:

AppIcon 的变更确认

5、清除变更 AppIcon 时系统弹出框

         我们知道系统的弹出框是由 UIAlertController 来实现的,它属于一个控制器。在弹出的时候会调用 presentViewController:animated:completion:   函数。那我们可以通过这个方法来阻止弹框的弹出。由于苹果系统的不开放性,我们也没发更改这个函数。目前,方法就是利用运行时,用我们创建的一个方法来替换这个方法。在我们的方法中来阻止弹框的弹出。

1、核心代码

该段代码可放在继承的控制器中或者在控制器中直接写。导入运行时的函数库 #import < objc/runtime.h >

#pragma mark 弹窗的清楚
+(void)load {
    Method  presentM = class_getInstanceMethod(self.class, @selector(presentViewController:animated:completion:));
    Method  presentAlternativeM = class_getInstanceMethod(self.class, @selector(clearPresentViewController:animated:completion:));
    // 方法的切换
    method_exchangeImplementations(presentM, presentAlternativeM);
}

#pragma mark 清楚处理方法
-(void)clearPresentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion{
    // 跳转页面的类型
    if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
        UIAlertController * alertVctl  = (UIAlertController *) viewControllerToPresent ;
        if (alertVctl.title == nil && alertVctl.message == nil) {
            return ;
        }
    }
    // 页面回调
    [self clearPresentViewController:viewControllerToPresent animated:flag completion:completion];
}

6、代码下载

  • 代码下载,可在博客下留言和邮箱。
  • 可添加QQ:群号:185341804 (成功QQ吧),联系群主获取。

猜你喜欢

转载自blog.csdn.net/zhoushuangjian511/article/details/80423399