咱們在平常開發中,常常遇到須要對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社區能有更多貢獻。