项目要上线了,产品要求跟安卓一样,一进去有一个提示框提示更新。虽然苹果在 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更新。就这样