咱们在平常开发中,常常遇到须要对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社区能有更多贡献。