版本更新的方式:

  1. 可选更新:弹框时有取消和更新两个按钮,用户可以选择取消按钮(增加新的功能,改善用户的体验等,这种更新不会影响软件的正常的使用)
  2. 强制更新:弹框时只有一个更新按钮,用户没得选择,必须更新(系统重大漏洞,严重影响用户正常使用等必须强制用户更新,不更新就不能使用该软件)

解决方案:

方案一:

调用服务器接口获取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;
}