Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSURLCache's removeCachedResponseForRequest has no effect

I've created an NSURLCache subclass which forces caching of responses for a designated amount of time. This is working well, and cached items are expired as expected. However I'm running into issues when trying to forcefully remove a cached response using NSURLCache's removeCachedResponseForRequest: method.

What I'm looking to achieve is to allow users to force an immediate reload of remote data. To do this, I pass an "ignoreCache" flag when making a request. I construct my NSURLRequest as normal, but ask my NSURLCache to remove any previously cached responses for the given request. This doesn't seem to have any effect, however, as the cached result is still present and used when the request is executed.

The documentation around NSURLCache is fairly sparse. The NSURLCache headers state that the NSURLRequest passed to removeCachedResponseForRequest: is used as a key to lookup the associated NSCachedURLResponse object, but there's little information given as to the logistics of that comparison. Does the NSURLCache class expect to receive the same NSURLRequest instance that generated the cached response, or does it simply compare the NSURL it represents?

Hopefully someone can point me in the right direction.

var error: NSError? = nil
var URLRequest: NSMutableURLRequest = self.operationManager.requestSerializer.requestWithMethod("GET", URLString: NSURL(string: request.URL, relativeToURL: self.operationManager.baseURL).absoluteString, parameters: request.parameters, error: &error)
URLRequest.cachePolicy = NSURLRequestCachePolicy.ReturnCacheDataElseLoad

// We've been asked to ignore the cache, so remove our previously cached response
if ignoreCache == true {
    NSURLCache.sharedURLCache().removeCachedResponseForRequest(URLRequest)
}

Here's the Swift code from my NSURLCache subclass for reference:

// MARK: - NSURLCache
override func cachedResponseForRequest(request: NSURLRequest!) -> NSCachedURLResponse! {
    var cachedResponse: NSCachedURLResponse? = super.cachedResponseForRequest(request)
    if(cachedResponse != nil && cachedResponse!.userInfo != nil) {
        var cacheDate: NSDate? = cachedResponse!.userInfo![self.cacheExpirationKey] as? NSDate
        if(cacheDate != nil) {
            var cacheDateLimit: NSDate = cacheDate!.dateByAddingTimeInterval(self.cacheExpirationInterval)
            if(cacheDate!.compare(NSDate()) == NSComparisonResult.OrderedAscending) {
                self.removeCachedResponseForRequest(request)
            } else {
                return cachedResponse
            }
        }
    }

    // Either our cached data was too old, or we don't have any that match the NSURLRequest
    return nil
}
override func storeCachedResponse(cachedResponse: NSCachedURLResponse!, forRequest request: NSURLRequest!) {
    var userInfo: NSMutableDictionary = NSMutableDictionary(dictionary: cachedResponse.userInfo)
    userInfo[cacheExpirationKey] = NSDate().dateByAddingTimeInterval(self.cacheExpirationInterval)

    var modifiedCacheResponse: NSCachedURLResponse = NSCachedURLResponse(response: cachedResponse.response, data: cachedResponse.data, userInfo: userInfo, storagePolicy: cachedResponse.storagePolicy)
    super.storeCachedResponse(modifiedCacheResponse, forRequest: request)
}
like image 466
ndg Avatar asked Mar 19 '23 14:03

ndg


1 Answers

Assuming you are on iOS 8, removeCachedResponseForRequest: does not work.

See http://blog.airsource.co.uk/2014/10/13/nsurlcache-ios8-broken-2/

like image 176
Airsource Ltd Avatar answered Apr 26 '23 04:04

Airsource Ltd