iOS不添加任何信息检测App更新
DarEames
8年前
<h3><strong>一.前言:</strong></h3> <ul> <li> <p>1.iOS开发中,有时会有这种需求,在AppStore上出现新版本时,应用内弹窗提示用户更新.</p> </li> <li> <p>2.之前在网上看到一种方法通过AppId查询更新的,但是有时候APP没上线或开发账号还没注册下来时我们并不知道AppId,此时就要把这个功能做上去,该怎么办呢?</p> </li> <li> <p>3.现介绍一种简便的方法给大家,不需要提供AppId等任何信息,即可实现查询AppStore中是否有新版本,并提示更新.</p> </li> <li> <p>4.代码地址:见篇尾.</p> </li> </ul> <h3><strong>二.效果:</strong></h3> <p style="text-align:center"><img src="https://simg.open-open.com/show/a7e05c1a7be0e41cf8ad691e16e29314.png"></p> <h3><strong>三.实现逻辑:</strong></h3> <ul> <li> <p>1.先查询AppStore中该App的信息(包含版本,更新日志等)</p> </li> <li> <p>2.和App当前版本进行比较,比当前版本新,弹窗并显示更新日志,提示用户跳转到AppStore更新</p> </li> <li> <p>3.为了方便在以后开发中调用,笔者实现时进行简单封装.</p> </li> </ul> <h3><strong>四.直接上代码:</strong></h3> <p>-4.1获取AppStore中该App的版本信息</p> <ul> <li> <p>1.为了不依赖其他数据请求库,笔者采用系统方法做数据请求,当然你们也可以使用AFN等框架请求数据.</p> </li> <li> <p>2.新建一个请求版本信息的类继承NSObject笔者取名 XHVersionRequest</p> </li> <li> <p>3.在XHVersionRequest.h文件中添加请求成功和失败回调和数据请求方法,代码如下:</p> </li> </ul> <pre> <code class="language-objectivec">#import typedef void(^RequestSucess) (NSDictionary * responseDict); typedef void(^RequestFailure) (NSError *error); @interface XHVersionRequest : NSObject /** * 从AppStore中获取App信息 * * @param success 成功回调 * @param failure 失败回调 */ +(void)xh_versionRequestSuccess:(RequestSucess)success failure:(RequestFailure)failure; @end</code></pre> <ul> <li> <p>4.在XHVersionRequest.m文件中实现</p> </li> </ul> <pre> <code class="language-objectivec">#import "XHVersionRequest.h" @implementation XHVersionRequest +(void)xh_versionRequestSuccess:(RequestSucess)success failure:(RequestFailure)failure{ NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; NSString *bundleId = infoDict[@"CFBundleIdentifier"]; NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@",bundleId]]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { dispatch_async(dispatch_get_main_queue(), ^{ if(!error) { NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]; if(success) success(responseDict); } else { if(failure) failure(error); } }); }]; [dataTask resume]; }); } @end</code></pre> <p>-4.2解析请求回来App信息数据</p> <ul> <li> <p>1.新建一个App信息模型继承NSObject,笔者取名XHAppInfo,为减少依赖,笔者暂不采用JSON -> Model 框架解析数据.</p> </li> <li> <p>2.在XHAppInfo.h和XHAppInfo.m中分别添加以下代码:</p> </li> <li> <p>XHAppInfo.h文件</p> </li> </ul> <pre> <code class="language-objectivec">#import #import @interface XHAppInfo : NSObject /** * 版本号 */ @property(nonatomic,copy) NSString * version; /** * 更新日志 */ @property(nonatomic,copy)NSString *releaseNotes; /** * 更新时间 */ @property(nonatomic,copy)NSString *currentVersionReleaseDate; /** * APPId */ @property(nonatomic,copy)NSString *trackId; /** * bundleId */ @property(nonatomic,copy)NSString *bundleId; /** * AppStore地址 */ @property(nonatomic,copy)NSString *trackViewUrl; - (instancetype)initWithResult:(NSDictionary *)result; @end</code></pre> <ul> <li> <p>XHAppInfo.m文件</p> </li> </ul> <pre> <code class="language-objectivec">#import "XHAppInfo.h" @implementation XHAppInfo - (instancetype)initWithResult:(NSDictionary *)result{ self = [super init]; if (self) { self.version = result[@"version"]; self.releaseNotes = result[@"releaseNotes"]; self.currentVersionReleaseDate = result[@"currentVersionReleaseDate"]; self.trackId = result[@"trackId"]; self.bundleId = result[@"bundleId"]; self.trackViewUrl = result[@"trackViewUrl"]; self.appDescription = result[@"appDescription"]; self.sellerName = result[@"sellerName"]; self.fileSizeBytes = result[@"fileSizeBytes"]; self.screenshotUrls = result[@"screenshotUrls"]; } return self; } @end</code></pre> <p>-4.3比较与当前版本大小关系,提示更新</p> <ul> <li> <p>1.笔者新建一个类XHVersion(继承NSObject)来处理版本比较和弹窗</p> </li> <li> <p>2.为了调用更灵活,我们在XHVersion.h文件中添加如下两个方法:1.一个是使用默认弹窗,2.一个是回调新版本信息,开发者自定义弹窗</p> </li> <li> <p>XHVersion.h文件</p> </li> </ul> <pre> <code class="language-objectivec">#import #import "XHAppInfo.h"typedef void(^NewVersionBlock)(XHAppInfo *appInfo);@interface XHVersion : NSObject/** * 检测新版本(使用默认提示框) */+(void)checkNewVersion;/** * 检测新版本(自定义提示框) * * @param newVersion 新版本信息回调 */+(void)checkNewVersionAndCustomAlert:(NewVersionBlock)newVersion;@end</code></pre> <ul> <li> <p>XHVersion.m文件中进行实现,代码如下</p> </li> </ul> <pre> <code class="language-objectivec">#import "XHVersion.h" #import "XHVersionRequest.h" @interface XHVersion()@property(nonatomic,strong)XHAppInfo *appInfo; @end @implementation XHVersion +(void)checkNewVersion{ [[XHVersion shardManger] checkNewVersion]; } +(void)checkNewVersionAndCustomAlert:(NewVersionBlock)newVersion{ [[XHVersion shardManger] checkNewVersionAndCustomAlert:newVersion]; } #pragma mark - private +(XHVersion *)shardManger{ static XHVersion *instance = nil; static dispatch_once_t oneToken; dispatch_once(&oneToken,^{ instance = [[XHVersion alloc] init]; }); return instance; } -(void)checkNewVersion{ [self versionRequest:^(XHAppInfo *appInfo) { NSString *updateMsg = [NSString stringWithFormat:@"%@",appInfo.releaseNotes]; #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"发现新版本" message:updateMsg delegate:self cancelButtonTitle:@"关闭" otherButtonTitles:@"更新", nil]; [alertView show]; #endif #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0 UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"发现新版本" message:updateMsg preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"关闭" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]]; [alert addAction:[UIAlertAction actionWithTitle:@"更新" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [self openInAppStoreForAppURL:self.appInfo.trackViewUrl]; }]]; [[self window].rootViewController presentViewController:alert animated:YES completion:nil]; #endif }]; } -(UIWindow *)window{ UIWindow *window = nil; id delegate = [[UIApplication sharedApplication] delegate]; if ([delegate respondsToSelector:@selector(window)]) { window = [delegate performSelector:@selector(window)]; } else { window = [[UIApplication sharedApplication] keyWindow]; } return window; } -(void)checkNewVersionAndCustomAlert:(NewVersionBlock)newVersion{ [self versionRequest:^(XHAppInfo *appInfo) { if(newVersion) newVersion(appInfo); }]; } -(void)versionRequest:(NewVersionBlock)newVersion{ [XHVersionRequest xh_versionRequestSuccess:^(NSDictionary *responseDict) { NSInteger resultCount = [responseDict[@"resultCount"] integerValue]; if(resultCount==1) { NSArray *resultArray = responseDict[@"results"]; NSDictionary *result = resultArray.firstObject; XHAppInfo *appInfo = [[XHAppInfo alloc] initWithResult:result]; NSString *version = appInfo.version; self.appInfo = appInfo; if([self isNewVersion:version])//新版本 { if(newVersion) newVersion(self.appInfo); } } } failure:^(NSError *error) { }]; } #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ if(buttonIndex==1) { [self openInAppStoreForAppURL:self.appInfo.trackViewUrl]; } } #endif -(void)openInAppStoreForAppURL:(NSString *)appURL{ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:appURL]]; } - (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController { [viewController dismissViewControllerAnimated:YES completion:nil]; } //是否是新版本 -(BOOL)isNewVersion:(NSString *)newVersion{ return [self newVersion:newVersion moreThanCurrentVersion:[self currentVersion]]; } -(NSString * )currentVersion{ NSString *key = @"CFBundleShortVersionString"; NSString * currentVersion = [NSBundle mainBundle].infoDictionary[key]; return currentVersion; } -(BOOL)newVersion:(NSString *)newVersion moreThanCurrentVersion:(NSString *)currentVersion{ if([currentVersion compare:newVersion options:NSNumericSearch]==NSOrderedAscending) { return YES; } return NO; }</code></pre> <h3><strong>五.调用:</strong></h3> <ul> <li> <p>导入头文件 #import "XHVersion.h" ,在需要检测新版本的地方调用下面代码</p> </li> </ul> <pre> <code class="language-objectivec">//1.新版本检测(使用默认提示框) [XHVersion checkNewVersion]; //2.如果你需要自定义提示框,请使用下面方法 [XHVersion checkNewVersionAndCustomAlert:^(XHAppInfo *appInfo) { //appInfo为新版本在AppStore相关信息 //请在此处自定义您的提示框 //...... }];</code></pre> <h3><strong>六.小结:</strong></h3> <ul> <li> <p>细看代码的同学可能会发现,笔者并没有通过AppId去拉取该App的版本信息,而是通过bundleId去查询的.</p> </li> </ul> <p> </p> <p> </p>