zoukankan      html  css  js  c++  java
  • 动态改变APP图标

    一、iOS动态更换App图标(一):基础使用

    该功能应用的场景

    1、白天/夜间模式切换,在切换App主色调同时切换App图标。

    2、各类皮肤主题(淘宝就可换肤),附带App图标一块更换。

    3、利用App图标表达某种特定功能,如Demo中的,提示当前天气。

    4、图标促销提示,如淘宝京东特定节日:11.11、6.18,提前更换App图标。

    当然该功能(API)当前只支持iOS10.3以上的系统,所以只能当做一项附加功能来进行使用。下面将详细讲解下如何使用代码来实现此功能。

    API方法

    @interface UIApplication (UIAlternateApplicationIcons)
    // 如果为NO,表示当前进程不支持替换图标
    @property (readonly, nonatomic) BOOL supportsAlternateIcons NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
    // 传入nil代表使用主图标. 完成后的操作将会在任意的后台队列中异步执行; 如果需要更改UI,请确保在主队列中执行.
    - (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));
    // 如果alternateIconName为nil,则代表当前使用的是主图标.
    @property (nullable, readonly, nonatomic) NSString *alternateIconName NS_EXTENSION_UNAVAILABLE("Extensions may not have alternate icons") API_AVAILABLE(ios(10.3), tvos(10.2));
    @end
    - (void)setAppIconWithName:(NSString *)iconName {
        if (![[UIApplication sharedApplication] supportsAlternateIcons]) {
            return;
        }
        
        if ([iconName isEqualToString:@""]) {
            iconName = nil;
        }
        [[UIApplication sharedApplication] setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
            if (error) {
                NSLog(@"更换app图标发生错误了 : %@",error);
            }
        }];
    }

    配置文件(Info.plist)

    当然也要拖入对应的App图标:

      不过这里我们好像还少配置了App主图标,也就是正常情况下我们的图标。按照文档所说,我们需要在CFBundleIcons里面配置CFBundlePrimaryIcon这个主图标对应的内容,但是实际上,我们还是按照老方法,在Assets.xcassets中配置AppIcon,对应尺寸填上对应图片即可。为什么这样子就可以配置主图标呢?让我们来看看某知名电商的ipa(在AppStore上下载的包)内的Info.plist(位于Payload/XXXXXX/Info.plist):

    拦截弹框

      既然知道了弹框是UIAlertController,那么我们自然而然想到,该弹框是由ViewController通过presentViewController:animated:completion:方法弹出。那么我们就可以通过Method swizzling hook该弹框,不让其进行弹出即可:

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

    或者

    #import "ViewController.h"
    #import <objc/runtime.h>
    
    
    // 利用runtime来替换展现弹出框的方法
        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(ox_presentViewController:animated:completion:));
            // 交换方法实现
            method_exchangeImplementations(presentM, presentSwizzlingM);
        });
    
    
    
    // 自己的替换展示弹出框的方法
    - (void)ox_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
        
        if ([viewControllerToPresent isKindOfClass:[UIAlertController class]]) {
            NSLog(@"title : %@",((UIAlertController *)viewControllerToPresent).title);
            NSLog(@"message : %@",((UIAlertController *)viewControllerToPresent).message);
            
            // 换图标时的提示框的title和message都是nil,由此可特殊处理
            UIAlertController *alertController = (UIAlertController *)viewControllerToPresent;
            if (alertController.title == nil && alertController.message == nil) {// 是换图标的提示
                return;
            } else {// 其他提示还是正常处理
                [self ox_presentViewController:viewControllerToPresent animated:flag completion:completion];
                return;
            }
        }
        
        [self ox_presentViewController:viewControllerToPresent animated:flag completion:completion];
    }

    这段代码交换了UIViewControllerpresentViewController:animated:completion:方法。通过打印UIAlertController的特征,我们可以发现,更换App图标时的弹框是没有title与message的,但是我们一般使用的UIAlertController都是带title、message的,毕竟不会弹个空白的框给用户玩。

    所以该方法中通过判断title与message来捕捉更换App图标时的弹框,并直接return即可。

    《iOS动态更换App图标(三):动态下载App图标进行更换》短期内应该无法实现

  • 相关阅读:
    AngularJS Insert Update Delete Using PHP MySQL
    Simple task manager application using AngularJS PHP MySQL
    AngularJS MySQL and Bootstrap Shopping List Tutorial
    Starting out with Node.js and AngularJS
    AngularJS CRUD Example with PHP, MySQL and Material Design
    How to install KVM on Fedora 22
    Fake_AP模式下的Easy-Creds浅析
    河南公务员写古文辞职信
    AI
    政协委员:最大愿望是让小学生步行上学
  • 原文地址:https://www.cnblogs.com/fengmin/p/6841818.html
Copyright © 2011-2022 走看看