緩存web數(shù)據(jù)

需要重寫(xiě)URLProtocol協(xié)議,重新定義startLoading()方法,網(wǎng)絡(luò)請(qǐng)求前嘗試從本地獲取,以便判斷是否已緩存。若無(wú),則發(fā)起請(qǐng)求,并緩存。

? ? //檢索緩存請(qǐng)求

? ? func cachedResponseForCurrentRequest() ->NSManagedObject? {

? ? ? ? //獲取管理的數(shù)據(jù)上下文 對(duì)象

? ? ? ? let app = UIApplication.shared.delegate as! AppDelegate

? ? ? ? let context = app.persistentContainer.viewContext

? ? ? ? //創(chuàng)建一個(gè)NSFetchRequest,通過(guò)它得到對(duì)象模型實(shí)體:CachedURLResponse

? ? ? ? let fetchRequest = NSFetchRequest()

? ? ? ? let entity =NSEntityDescription.entity(forEntityName:"CachedURLResponse",

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? in: context)

? ? ? ? fetchRequest.entity= entity

? ? ? ? //設(shè)置查詢條件

? ? ? ? let predicate =NSPredicate(format:"url == %@",self.request.url!.absoluteString)

? ? ? ? fetchRequest.predicate= predicate

? ? ? ? //執(zhí)行獲取到的請(qǐng)求

? ? ? ? do{

? ? ? ? ? ? let possibleResult =trycontext.fetch(fetchRequest)

? ? ? ? ? ? ? ? as? Array

? ? ? ? ? ? if let result = possibleResult {

? ? ? ? ? ? ? ? if !result.isEmpty{

? ? ? ? ? ? ? ? ? ? returnresult[0]

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? catch{

? ? ? ? ? ? print("獲取緩存數(shù)據(jù)失?。篭(error)")

? ? ? ? }

? ? ? ? returnnil

? ? }


//開(kāi)始處理這個(gè)請(qǐng)求

? ? override func startLoading() {

? ? ? ? requestCount+=1

? ? ? ? print("Request請(qǐng)求\(requestCount): \(request.url!.absoluteString)")

? ? ? ? //判斷是否有本地緩存

? ? ? ? let possibleCachedResponse =self.cachedResponseForCurrentRequest()

? ? ? ? if let cachedResponse = possibleCachedResponse {

? ? ? ? ? ? print("----- 從緩存中獲取響應(yīng)內(nèi)容 -----")

? ? ? ? ? ? //從本地緩中讀取數(shù)據(jù)

? ? ? ? ? ? let data = cachedResponse.value(forKey:"data")as!Data!

? ? ? ? ? ? let mimeType = cachedResponse.value(forKey:"mimeType")as!String!

? ? ? ? ? ? let encoding = cachedResponse.value(forKey:"encoding")as!String!

? ? ? ? ? ? //創(chuàng)建一個(gè)NSURLResponse 對(duì)象用來(lái)存儲(chǔ)數(shù)據(jù)。

? ? ? ? ? ? letresponse =URLResponse(url:self.request.url!, mimeType: mimeType,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? expectedContentLength: data!.count,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? textEncodingName: encoding)

? ? ? ? ? ? //將數(shù)據(jù)返回到客戶端。然后調(diào)用URLProtocolDidFinishLoading方法來(lái)結(jié)束加載。

? ? ? ? ? ? //(設(shè)置客戶端的緩存存儲(chǔ)策略.NotAllowed ,即讓客戶端做任何緩存的相關(guān)工作)

? ? ? ? ? ? self.client!.urlProtocol(self, didReceive: response,

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cacheStoragePolicy: .notAllowed)

? ? ? ? ? ? self.client!.urlProtocol(self, didLoad: data!)

? ? ? ? ? ? self.client!.urlProtocolDidFinishLoading(self)

? ? ? ? }else{

? ? ? ? ? ? //請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)

? ? ? ? ? ? print("===== 從網(wǎng)絡(luò)獲取響應(yīng)內(nèi)容 =====")

? ? ? ? ? ? let newRequest = (self.request as NSURLRequest).mutableCopy() as! NSMutableURLRequest

? ? ? ? ? ? //NSURLProtocol接口的setProperty()方法可以給URL請(qǐng)求添加自定義屬性。

? ? ? ? ? ? //(這樣把處理過(guò)的請(qǐng)求做個(gè)標(biāo)記,下一次就不再處理了,避免無(wú)限循環(huán)請(qǐng)求)

? ? ? ? ? ? URLProtocol.setProperty(true, forKey: "MyURLProtocolHandledKey",

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? in: newRequest)


? ? ? ? ? ? //使用URLSession從網(wǎng)絡(luò)獲取數(shù)據(jù)

? ? ? ? ? ? let defaultConfigObj =URLSessionConfiguration.default

? ? ? ? ? ? let defaultSession = Foundation.URLSession(configuration: defaultConfigObj,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delegate:self, delegateQueue:nil)

? ? ? ? ? ? self.dataTask= defaultSession.dataTask(with:self.request)

? ? ? ? ? ? self.dataTask!.resume()

? ? ? ? }

? ? }


? ? //保存獲取到的請(qǐng)求響應(yīng)數(shù)據(jù)

? ? func saveCachedResponse () {

? ? ? ? print("+++++ 將獲取到的數(shù)據(jù)緩存起來(lái) +++++")

? ? ? ? //獲取管理的數(shù)據(jù)上下文 對(duì)象

? ? ? ? let app = UIApplication.shared.delegate as! AppDelegate

? ? ? ? let context = app.persistentContainer.viewContext

? ? ? ? //創(chuàng)建NSManagedObject的實(shí)例,來(lái)匹配在.xcdatamodeld 文件中所對(duì)應(yīng)的數(shù)據(jù)模型。

? ? ? ? let cachedResponse = NSEntityDescription

? ? ? ? ? ? .insertNewObject(forEntityName:"CachedURLResponse",

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? into: context)asNSManagedObject

? ? ? ? cachedResponse.setValue(self.receivedData, forKey:"data")

? ? ? ? cachedResponse.setValue(self.request.url!.absoluteString, forKey:"url")

? ? ? ? cachedResponse.setValue(Date(), forKey:"timestamp")

? ? ? ? cachedResponse.setValue(self.urlResponse?.mimeType, forKey:"mimeType")

? ? ? ? cachedResponse.setValue(self.urlResponse?.textEncodingName, forKey:"encoding")

? ? ? ? //保存(Core Data數(shù)據(jù)要放在主線程中保存,要不并發(fā)是容易崩潰)

? ? ? ? DispatchQueue.main.async(execute: {

? ? ? ? ? ? do{

? ? ? ? ? ? ? ? trycontext.save()

? ? ? ? ? ? }catch{

? ? ? ? ? ? ? ? print("不能保存:\(error)")

? ? ? ? ? ? }

? ? ? ? })

? ? }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容