NSURLProtocol。 requestIsCacheEquivalent从未调用过

我不确定交易在这里,但功能:

class func requestIsCacheEquivalent(a: NSURLRequest, toRequest b: NSURLRequest) -> Bool

永远不会在我的NSURLProtocol子类中调用。 我甚至看到了使用缓存的情况(通过使用网络代理进行验证,并且没有发现任何调用),但是此方法从未被调用。 为什么这是我亏本的。

我试图解决的问题是我有要缓存数据的请求,但这些请求有一个签名参数,每个签名参数都不相同(类似于一个随机数)。 这使得缓存键不同,尽管数据是等价的。

进入明确的细节:

  • 我用自定义签名www.example.com?param1=1&param2=2&signature=1abcdefabc312093请求(如下所示: www.example.com?param1=1&param2=2&signature=1abcdefabc312093 signature= www.example.com?param1=1&param2=2&signature=1abcdefabc312093
  • 该请求返回一个Etag
  • Etag应该由NSURLCache进行管理,但是由于它认为正在创建不同的请求( www.example.com?param1=1&param2=2&signature=1abdabcda3359809823 param2 = 2&signature = 1abdabcda3359809823),所以不需要麻烦。
  • 我认为使用NSURLProtocol将解决我所有的问题,因为苹果的文档说:

    class func requestIsCacheEquivalent(_ aRequest: NSURLRequest,
                          toRequest bRequest: NSURLRequest) -> Bool
    

    如果aRequest和bRequest等同于缓存目的,则为YES,否则为否。 只有当它们由同一个协议处理并且该协议在执行特定于实现的检查之后声明它们相同时,请求才被视为等同于缓存目的。

    可悲的是,该功能从未被调用。 我不知道问题可能是什么...

    class WWURLProtocol : NSURLProtocol, NSURLSessionDataDelegate {
    var dataTask: NSURLSessionDataTask?
    var session: NSURLSession!
    var trueRequest: NSURLRequest!
    
    private lazy var netOpsQueue: NSOperationQueue! = NSOperationQueue()
    private lazy var delegateOpsQueue: NSOperationQueue! = NSOperationQueue()
    
    override class func canInitWithRequest(request: NSURLRequest) -> Bool {
        println("can init with request called")
        return true
    }
    
    override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
        println("canonical request for request called")
        return request
    }
    
    override class func requestIsCacheEquivalent(a: NSURLRequest, toRequest b: NSURLRequest) -> Bool     {
        // never ever called?!?
        let cacheKeyA = a.allHTTPHeaderFields?["CacheKey"] as? String
        let cacheKeyB = b.allHTTPHeaderFields?["CacheKey"] as? String
    
        println("request is cache equivalent? (cacheKeyA) == (cacheKeyB)")
    
        return cacheKeyA == cacheKeyB
    }
    
    override func startLoading() {
        println("start loading")
    
        let sharedSession = NSURLSession.sharedSession()
        let config = sharedSession.configuration
        config.URLCache = NSURLCache.sharedURLCache()
        self.session = NSURLSession(configuration: config, delegate: self, delegateQueue: self.delegateOpsQueue)
    
        dataTask = session.dataTaskWithRequest(request, nil)
        dataTask?.resume()
    }
    
    override func stopLoading() {
        println("stop loading")
        dataTask?.cancel()
    }
    
    
    //SessionDelegate
    
    func URLSession(session: NSURLSession, didBecomeInvalidWithError error: NSError?) {
        println("did become invalid with error")
        client?.URLProtocol(self, didFailWithError: error!)
    }
    
    
    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        println("did complete with error")
        if error == nil {
            client?.URLProtocolDidFinishLoading(self)
        } else {
            client?.URLProtocol(self, didFailWithError: error!)
        }
    }
    
    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
        println("did receive response")
        client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .Allowed)
        completionHandler(.Allow)
    }
    
    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
        println("did receive data called")
        client?.URLProtocol(self, didLoadData: data)
    }
    
    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, willCacheResponse proposedResponse: NSCachedURLResponse, completionHandler: (NSCachedURLResponse!) -> Void) {
        println("will cache response called")
        client?.URLProtocol(self, cachedResponseIsValid: proposedResponse)
    
        completionHandler(proposedResponse)
    }
    

    我在我的应用程序委托中注册了该协议,如下所示:

    NSURLProtocol.registerClass(WWURLProtocol.self)
    

    我触发协议如下:

    @IBAction func requestData(endpointString: String) {
        let url = NSURL(string: endpointString)
        let request = NSMutableURLRequest(URL: url!)
        var cacheKey = endpointString
        request.setValue("(endpointString)", forHTTPHeaderField: "CacheKey")
        request.cachePolicy = .UseProtocolCachePolicy
    
        NSURLConnection.sendAsynchronousRequest(request, queue: netOpsQueue) { (response, data, error) -> Void in
            if data != nil {
                println("succeeded with data:(NSString(data: data, encoding: NSUTF8StringEncoding)))")
            }
        }
    
    }
    

    我认为在实践中,加载系统只是使用规范化的URL来实现缓存目的,并进行直接字符串比较。 不过,我不确定。 尝试附加您的随机数,当您规范化时,以某种易于移除/检测的形式(如果它已经存在)。


    你的代码看起来没问题。你只需要遵循苹果有关URLProtocol文档。你可以尝试使用URLSession for NSURLConnection在新版本的iOS版本中被弃用。祝你好运。

    链接地址: http://www.djcxy.com/p/34787.html

    上一篇: NSURLProtocol. requestIsCacheEquivalent never called

    下一篇: UIWebView simulator suddenly not working