缓存web数据

需要重写URLProtocol协议,重新定义startLoading()方法,网络请求前尝试从本地获取,以便判断是否已缓存。若无,则发起请求,并缓存。

    //检索缓存请求

    func cachedResponseForCurrentRequest() ->NSManagedObject? {

        //获取管理的数据上下文 对象

        let app = UIApplication.shared.delegate as! AppDelegate

        let context = app.persistentContainer.viewContext

        //创建一个NSFetchRequest,通过它得到对象模型实体:CachedURLResponse

        let fetchRequest = NSFetchRequest()

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

                                                       in: context)

        fetchRequest.entity= entity

        //设置查询条件

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

        fetchRequest.predicate= predicate

        //执行获取到的请求

        do{

            let possibleResult =trycontext.fetch(fetchRequest)

                as? Array

            if let result = possibleResult {

                if !result.isEmpty{

                    returnresult[0]

                }

            }

        }

        catch{

            print("获取缓存数据失败:\(error)")

        }

        returnnil

    }


//开始处理这个请求

    override func startLoading() {

        requestCount+=1

        print("Request请求\(requestCount): \(request.url!.absoluteString)")

        //判断是否有本地缓存

        let possibleCachedResponse =self.cachedResponseForCurrentRequest()

        if let cachedResponse = possibleCachedResponse {

            print("----- 从缓存中获取响应内容 -----")

            //从本地缓中读取数据

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

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

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

            //创建一个NSURLResponse 对象用来存储数据。

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

                                         expectedContentLength: data!.count,

                                         textEncodingName: encoding)

            //将数据返回到客户端。然后调用URLProtocolDidFinishLoading方法来结束加载。

            //(设置客户端的缓存存储策略.NotAllowed ,即让客户端做任何缓存的相关工作)

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

                                     cacheStoragePolicy: .notAllowed)

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

            self.client!.urlProtocolDidFinishLoading(self)

        }else{

            //请求网络数据

            print("===== 从网络获取响应内容 =====")

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

            //NSURLProtocol接口的setProperty()方法可以给URL请求添加自定义属性。

            //(这样把处理过的请求做个标记,下一次就不再处理了,避免无限循环请求)

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

                                      in: newRequest)


            //使用URLSession从网络获取数据

            let defaultConfigObj =URLSessionConfiguration.default

            let defaultSession = Foundation.URLSession(configuration: defaultConfigObj,

                                              delegate:self, delegateQueue:nil)

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

            self.dataTask!.resume()

        }

    }


    //保存获取到的请求响应数据

    func saveCachedResponse () {

        print("+++++ 将获取到的数据缓存起来 +++++")

        //获取管理的数据上下文 对象

        let app = UIApplication.shared.delegate as! AppDelegate

        let context = app.persistentContainer.viewContext

        //创建NSManagedObject的实例,来匹配在.xcdatamodeld 文件中所对应的数据模型。

        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数据要放在主线程中保存,要不并发是容易崩溃)

        DispatchQueue.main.async(execute: {

            do{

                trycontext.save()

            }catch{

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

            }

        })

    }

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容