項目要上線了,產品要求跟安卓一樣,一進去有一個提示框提示更新。雖然蘋果在 Settings/iTunes Store & App Store 選項中有自動更新這一選項,而且添加版本號等等有被拒絕的危險。但是..總之我建議大家要據理力爭。不過既然需求下來了,我們應該怎么做呢?
按照與之前的思路,我們是獲取本地的版本號,以及從AppStore下載下來最新的版本號,兩者進行比較,若本地版本號較低,則跳轉至AppStore進行更新。首次使用Swift語言挑戰,可能會有預知不到的錯誤,這樣我們就分步做一下。
1.獲取本地版本號
最簡單。直接上代碼。
1 // 取出本地版本號 2 let localVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
通過目錄列表的信息字典,取出本地版本號。
2.獲取AppStore的版本號
這個我們需要通過特定網址,請求AppStore的版本信息並解析出來。邊上代碼邊分析:
2.1 配置網絡請求
1 // AppStore地址(字符串) 2 let path = NSString(format: "http://itunes.apple.com/cn/lookup?id=%@", appStoreId) as String 3 4 // AppStore地址(URL) 5 let url = NSURL(string: path) 6 7 // 配置網絡請求參數 8 let request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData, timeoutInterval: 10.0) 9 request.HTTPMethod = "POST"
這里需要說明的一點是:cachePolicy的意思是緩存機制;其類型是個枚舉,有以下幾項:(自我感覺跑題了..)
1 public enum NSURLRequestCachePolicy : UInt { 2 3 case UseProtocolCachePolicy // 默認行為 4 5 case ReloadIgnoringLocalCacheData // 不使用緩存 6 case ReloadIgnoringLocalAndRemoteCacheData // Unimplemented (未實現) // 不使用任何緩存 7 public static var ReloadIgnoringCacheData: NSURLRequestCachePolicy { get } 8 9 case ReturnCacheDataElseLoad // 使用緩存(不管它是否過期),如果緩存中沒有,那從網絡加載吧 10 case ReturnCacheDataDontLoad // 離線模式:使用緩存(不管它是否過期),但是不從網絡加載 11 12 case ReloadRevalidatingCacheData // Unimplemented (未實現) // 在使用前去服務器驗證 13 }
我們選擇的是 ReloadIgnoringLocalCacheData ,也就是不使用緩存;畢竟版本號是隨時更新的。
2.2 請求網絡
1 // 開始網絡請求 2 NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) { (response, data, error) in 3 4 // 聲明獲取的數據字典 5 let receiveStatusDic = NSMutableDictionary() 6 7 if data != nil { 8 9 do { 10 // JSON解析data 11 let dic = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) 12 13 // 取出版本號 14 // 判斷是否resultCount為空 15 if let resultCount = dic["resultCount"] as? NSNumber { 16 17 // 判斷resultCount的數量是否大於0 18 if resultCount.integerValue > 0 { 19 20 // 設置請求狀態(1代表成功,0代表失敗) 21 receiveStatusDic.setValue("1", forKey: "status") 22 23 // 判斷results是否為空 24 if let arr = dic["results"] as? NSArray { 25 26 if let dict = arr.firstObject as? NSDictionary { 27 28 // 取出version 29 if let version = dict["version"] as? String { 30 31 receiveStatusDic.setValue(version, forKey: "version") 32 33 // 存網絡版本號到UserDefaults里面 34 NSUserDefaults.standardUserDefaults().setObject(version, forKey: "Version") 35 36 NSUserDefaults.standardUserDefaults().synchronize() 37 } 38 } 39 } 40 } 41 } 42 }catch let error { 43 44 print("checkUpdate -------- \(error)") 45 46 receiveStatusDic.setValue("0", forKey: "status") 47 } 48 }else { 49 50 receiveStatusDic.setValue("0", forKey: "status") 51 } 52 53 // 取出版本號后(若有則status為1,若沒有則status為0),執行方法 54 self.performSelectorOnMainThread(#selector(self.checkUpdateWithData(_:)), withObject: receiveStatusDic, waitUntilDone: false) 55 }
沒有使用三方庫諸如AFNetWorking或者SwiftHTTP來請求網絡,主要是考慮三方庫的版本差異;使用的系統的 NSURLConnection 進行網絡請求,不過似乎過期了,應該使用NSURLSession;使用 NSJSONSerialization 來解析JSON數據。不要看步驟多,主要用來判斷數據是否為空以及添加請求結果的狀態了。同時將AppStore中的版本信息緩存到NSUserDefaults中,緩存一下。最后將請求后的數據與請求狀態傳遞至處理數據的方法中即可。
3.判斷版本號
1 // 判斷版本號 2 @objc private func checkUpdateWithData(data: NSDictionary) { 3 4 // 判斷請求網絡版本號的狀態 5 let status = data["status"] as? String 6 7 // 取出本地版本號 8 let localVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String 9 10 if status == "1" { 11 12 let storeVersion = data["version"] as! String 13 14 self.compareVersion(localVersion, storeVersion: storeVersion) 15 16 return 17 } 18 19 if let storeVersion = NSUserDefaults.standardUserDefaults().objectForKey("Version") as? String { 20 21 self.compareVersion(localVersion, storeVersion: storeVersion) 22 } 23 }
沒啥好說的,對比兩個版本號。若本地版本號較低,則執行下面的方法(跳轉AppStore更新或者單純的提醒一下用戶該更新了)。
4.更新
1 private func compareVersion(localVersion: String, storeVersion: String) { 2 3 if localVersion.compare(storeVersion) == NSComparisonResult.OrderedAscending { 4 5 //做你想做的事情 6 let alertController = UIAlertController.init(title: "更新可用", message: "\(NSBundle.mainBundle().infoDictionary!["CFBundleDisplayName"])的新版本可用。請立即更新至\(storeVersion)。", preferredStyle: UIAlertControllerStyle.Alert) 7 8 let confirmAction = UIAlertAction.init(title: "更新", style: UIAlertActionStyle.Default, handler: { (alertAction) in 9 10 11 }) 12 13 let nextTimeAction = UIAlertAction.init(title: "下一次", style: UIAlertActionStyle.Cancel, handler: nil) 14 15 alertController.addAction(confirmAction) 16 alertController.addAction(nextTimeAction) 17 18 self.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil) 19 } 20 }
我做的是跳轉AppStore更新。就這樣