App启动更新

咱们在平常开发中,常常遇到须要对app进行更新的问题,除了在app store中找到你的应用并更新,还能够在app内提示应用更新,这种方式的场景是,当咱们的app过审,咱们须要在同一时间告知用户,咱们的新版本已经发布,并根据要求用户更新的急缓程度,采用软更和强更的方式,完成版本更新。bash

选择更新方式

推送更新的方式有多种,但通常都是在启动时,经过对比版本并决定是否要参与更新:网络

1.跟服务端录好的版本号配对,这种方式更新的掌握权在运营者本身身上,能够决定须要跟新的时间,统一放出更新消息。服务端推更和应用内推送推更的原理同样,基于推更稳定和服务人群数量,各有利弊。session

2.跟iTunes 上的版本号对比,也是在每次启动时,比较版本,提示更新,这种作法更为直接。app

如何选择适合本身的更新,具体要根据产品定位来设计。ui

代码

这里只介绍iTunes方式。
url

1.比较更新spa

GGXVersion.h设计

+ (instancetype)share;
- (void)showVersion:(void (^)(NSString *))version;复制代码

GGXVersion.m
代理

+ (instancetype)share {
    static GGXVersion *ggxVersion = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        ggxVersion = [[GGXVersion alloc] init];
    });
    return ggxVersion;
}
//获取最新版本号
- (void)showVersion:(void (^)(NSString *))version {
    [self request:^(NSString *storeVersion) {
        NSLog(@"version %@",storeVersion);
        NSString *new = [self compVersion:storeVersion];
        version(new);
    }];
}
/**
 typedef enum _NSComparisonResult {
 NSOrderedAscending = -1,    // <
 NSOrderedSame,              // =
 NSOrderedDescending         // >
 } NSComparisonResult;
 */
//比较版本大小
- (NSString *)compVersion:(NSString *)storeVersion {
    NSString *bundleVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    //v1>v2
    if ([storeVersion compare:bundleVersion options:NSNumericSearch] == NSOrderedDescending)
        NSLog(@"须要更新,store最新版本是: %@",storeVersion);
        return storeVersion;
}
//NSURLSession请求
- (void)request:(void (^)(NSString *))comp {
    //请求地址
    NSURL *url = [NSURL URLWithString:@"https://itunes.apple.com/cn/lookup?id=1438938483"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    /* 发送HTTPS请求是须要对网络会话设置代理的 */
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        if (error == nil) {
            //返回的数据
            NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
            NSArray *res = dict[@"results"];
            //NSLog(@"%@",dict);
            if (res.count > 0) {
                NSString *storeVersion = res[0][@"version"];
                comp(storeVersion);
            }
        }
    }];
    [dataTask resume];
}
// 请求身份验证,遵循协议<NSURLSessionDataDelegate>
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    // 提供身份验证请求的信息
    NSLog(@"被保护空间 %@",challenge.protectionSpace);
    // NSURLAuthenticationMethodServerTrust: ServerTrust认证,适用于任何协议
    if (![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
        return;
    }
    NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
    completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}
复制代码

2.封装提示框
code

GGXAlert.h

/**
 初始化弹框

 @param vc alert添加到哪层,默认window
 @param title 标题
 @param message 描述内容
 @param style alert样式
 @param titleArray 须要建立的按钮数量
 @param cancel 是否须要建立【取消】,默认不建立,按钮名称本身定义
 @param alertAction 回调按钮对应下标
 */
+ (void)alertControllerWithVC:(UIViewController *__nullable)vc title:(NSString *)title message:(NSString *)message style:(UIAlertControllerStyle)style titleArray:(NSArray *)titleArray needCancel:(NSString *__nullable)cancel alertAction:(void (^)(NSInteger index))alertAction;复制代码

GGXAlert.m

+ (void)alertControllerWithVC:(UIViewController *__nullable)vc title:(NSString *)title message:(NSString *)message style:(UIAlertControllerStyle)style titleArray:(NSArray *)titleArray needCancel:(NSString *__nullable)cancel alertAction:(void (^)(NSInteger))alertAction {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:style];
    for (NSInteger i = 0; i < titleArray.count; i++) {
        UIAlertAction *confirm = [UIAlertAction actionWithTitle:titleArray[i] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            if (alertAction) {
                alertAction(i);
            }
        }];
        [alert addAction:confirm];
        
    }
    if (cancel != nil) {
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            if (alertAction) {
                alertAction(titleArray.count);
            }
        }];
        [alert addAction:cancelAction];
    }
    [self showUPdate:alert currentVC:vc];
    
}
+ (void)showUPdate:(UIAlertController *)alert currentVC:(UIViewController *__nullable)vc {
    
    if (!vc) {
        UIWindow   *alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        alertWindow.rootViewController = [[UIViewController alloc] init];
        alertWindow.windowLevel = UIWindowLevelAlert + 1;
        [alertWindow makeKeyAndVisible];
        [alertWindow.rootViewController presentViewController:alert animated:YES completion:nil];
    }else {
        [vc presentViewController:alert animated:YES completion:nil];
    }
    
}
复制代码

因为在代码中设置alert默认在window最上层,除非覆盖,另外咱们还能够将alert直接添加到当前视图中

3.实现

AppDelegate.m

GGXVersion *gxv = [GGXVersion share];
    [gxv showVersion:^(NSString * _Nonnull version) {
        NSString *title = [NSString stringWithFormat:@"最新版本 %@",version];
        [GGXAlert alertControllerWithVC:nil title:title message:@"发现新版本,是否当即更新?" style:UIAlertControllerStyleAlert titleArray:@[@"当即升级"] needCancel:@"下次再说" alertAction:^(NSInteger index) {
            if (index == 0) {
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://apps.apple.com/kh/app/super-fowlst/id1438938483"]];
                exit(0);
            }

        }];
    }];复制代码

这里有必要说一下 exit(0)终止程序,若是咱们须要使用强更,在跳转下载页面后再次跳回app会再次提示弹窗,这里作了一个障眼法,看似回到app后保持原页面,实则已经终止程序而是再次启动,可是建议通常状况下不要过于依赖exit,会形成用户体验很差。


最后

咱们将要说一下软更新和强更新

软更新有更多可选内容,用户不更新也能够作到正常使用。咱们能够设置更新暂不提醒、跳过,更新:用户跳转到下载页面,即便不下载再次回到app依然可使用;暂不提醒:设置一个周期,好比三天,会再次弹出这个更新提醒;跳过:再次启动app依然提醒用户更新。

强更新,用户没法选择,只有赞成更新才能继续使用应用。

纯属我的分享,但愿对iOS社区能有更多贡献。

相关文章
相关标签/搜索