首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSURLProtocol。requestIsCacheEquivalent从未调用过

NSURLProtocol。requestIsCacheEquivalent从未调用过
EN

Stack Overflow用户
提问于 2015-01-19 16:29:00
回答 2查看 727关注 0票数 2

我不知道这笔交易是什么,但功能是:

代码语言:javascript
复制
class func requestIsCacheEquivalent(a: NSURLRequest, toRequest b: NSURLRequest) -> Bool

从未在我的NSURLProtocol子类中调用。我甚至见过使用缓存的情况(通过使用网络代理进行验证,并且没有看到调用),但是这个方法从来没有被调用过。我不明白这是为什么。

我试图解决的问题是,我有希望缓存数据的请求,但是这些请求有一个针对每个请求的签名参数(有点像现在)。这使得缓存键不一样,尽管数据是等价的。

要进入明确的细节:

  1. 使用自定义签名触发请求(如:www.example.com?param1=1&param2=2&signature=1abcdefabc312093)
  2. 请求带着一个Etag返回。
  3. Etag应该由NSURLCache来管理,但是由于它认为正在发出一个不同的请求(www.example.com?param1=1&param2=2&signature=1abdabcda3359809823),所以不会麻烦。

我认为使用NSURLProtocol可以解决我所有的问题,因为苹果的文档说:

代码语言:javascript
复制
class func requestIsCacheEquivalent(_ aRequest: NSURLRequest,
                      toRequest bRequest: NSURLRequest) -> Bool

是的,如果aRequest和bRequest在缓存目的上是等价的,则没有其他的。对于缓存目的来说,请求被认为是等价的,只有当请求被同一协议处理时,并且在执行特定于实现的检查之后,该协议声明它们是等效的。

遗憾的是,这个函数从未被调用过。我不知道有什么问题..。

代码语言:javascript
复制
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)
}

我在我的应用程序代表中注册了协议如下:

代码语言:javascript
复制
NSURLProtocol.registerClass(WWURLProtocol.self)

我触发该议定书如下:

代码语言:javascript
复制
@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)))")
        }
    }

}
EN

回答 2

Stack Overflow用户

发布于 2015-10-28 19:41:39

我认为在实践中,加载系统只是使用规范化的URL作为缓存的目的,并做一个直接的字符串比较。不过我不确定。当你将它规范化时,试着附加你的现在,以一种很容易移动/探测的形式(万一它已经在那里)。

票数 0
EN

Stack Overflow用户

发布于 2017-03-03 07:51:11

您的代码似乎所有的right.You都是按照苹果的文档编写的,URLProtocol.You可以尝试使用URLSession,因为NSURLConnection在较新的iOS version.Good运气中是不推荐的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28029252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档