版本更新的方式:
- 可选更新:弹框时有取消和更新两个按钮,用户可以选择取消按钮(增加新的功能,改善用户的体验等,这种更新不会影响软件的正常的使用)
- 强制更新:弹框时只有一个更新按钮,用户没得选择,必须更新(系统重大漏洞,严重影响用户正常使用等必须强制用户更新,不更新就不能使用该软件)
解决方案:
方案一:
调用服务器接口获取App的版本号,如果服务器的版本号大于当前App的版本号,那么则弹框提示更新,否则就不提示
方案二:
获取App Store 上的应用的版本号,如果App Store 上的版本号大于当前App的版本号,那么则弹框提示更新,否则就不提示
两种方案比较:
方式二是调用App Store对应的接口,由于App Store服务器在外国,可能请求比较慢或者连接失败,网络不稳定;再者这种方式不能确定该版本是否是强制更新类型的;还有该方式只能用于iOS, 这让Android怎么办?这种方式唯一的优点就是可以App审核通过后,用户能在第一时间进行更新
方式一是调用自己应用的服务器,网速稳定,比较灵活,可以在接口中任意定义字段如最新版本号、是否强制更新isForceUpdate 等参数;因App Store 审核需要2-3天时间,不能及时知道什么时候审核通过,可能会出现审核通过了,开发人员还不知道,这段时间获取应用的版本信息接口可能版本号还是老的,这段时间还不能更新,没有达到第一时间就能更新的效果
方法一:获取自己服务器版本号检查
1. 通过网络请求获取服务器上的版本号;
2. 获取当前应用版本号;
3. 将版本号转换为整形进行比较;
4. 如果有版本更新则跳转到app store上下载。
方法二:获取app store上架版本号检查
1. 通过网络同步请求获取app store上对应APP ID的应用信息;
2. 提取信息上的最新版本号和下载地址;
3. 获取当前应用版本号;
4. 将版本号转换成双精度型进行比较;
5. 对于有两个点的版本号的最后一个点不处理。
iTunes Search API 查询应用程序信息,包括作者,版本,app 介绍页面地址等信息
获取App Store中的应用信息接口
App有两个版本号,一个是Version,另一个是Build,对应于Info.plist的字段名分别为CFBundleShortVersionString,CFBundleVersion。 AppSotre默认取的是Version即CFBundleShortVersionString
方式二代码示例:
#import "AppDelegate.h"
#import <AFNetworking.h>
@interface AppDelegate () <UIAlertViewDelegate>
@property (strong, nonatomic) NSString *trackViewUrl;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
NSString *APPID = @"123456789";
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:@"https://itunes.apple.com/lookup" parameters:@{@"id": APPID} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary * _Nullable responseObject) {
/*
results:[
{
trackViewUrl = "https://itunes.apple.com/us/app/xxx/id123456789?mt=8&uo=4";
version = "1.7.4"
}
]*/
NSLog(@"%@", responseObject);
NSArray *results = responseObject[@"results"];
NSString *version = [[results objectAtIndex:0] objectForKey:@"version"];
self.trackViewUrl = [[results objectAtIndex:0] objectForKey:@"trackViewUrl"];
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
float shortVersion = [infoDict[@"CFBundleShortVersionString"] floatValue];
if ([version floatValue] > shortVersion) {
NSString * title = [NSString stringWithFormat:@"检查更新: %@", @"应用名称"];
NSString * message = [NSString stringWithFormat:@"发现新版本(%@), 是否升级 ?", version];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"升级", nil];
[alertView show];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
self.window.rootViewController = [[UIViewController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
NSURL *trackViewUrl = [NSURL URLWithString:self.trackViewUrl];
UIApplication *application = [UIApplication sharedApplication];
if ([application canOpenURL:trackViewUrl]) {
[application openURL:trackViewUrl];
}
}
}
方式一的代码和方式二差不多,只不过是请求自己应用的服务器接口,然后解析
第三方实现
第三方实现的思路一般都是上面的思路,只不过对上述代码进行封装了,比如如果将appId作为参数或者直接获取应用的bundleId,对于UIAlertView的title,message,buttonTitle作为参数提取出来,提供更简洁的方法来使用。
https://github.com/emotality/ATAppUpdate 只需要一行代码就能集成版本更新
实现逻辑是根据Bundle Identifier 去查找应用信息的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ATAppUpdater *updater = [ATAppUpdater sharedUpdater];
updater.alertTitle = @"版本升级";
updater.alertMessage = @"最新版本位为:%@ ";
updater.alertCancelButtonTitle = @"暂不更新";
updater.alertUpdateButtonTitle = @"马上更新";
[updater showUpdateWithConfirmation];
return YES;
}