SDURLCache
SDURLCache copied to clipboard
Cache in offline
Hi,
This is not a bug but a comment about offline use of SDURLCache.
I'm trying to use SDURLCache to make an offline cache for UIWebView. Actually it doesn't work as in offline I get an error "no connexion available" (no sure about the english message). Code=-1009.
So what I did to solve this problem is to change the cachedResponseForRequest: method to create a new NSCachedURLResponse from the cache instance. This trick works for almost all resources except the JQuery AJAX request because it seems that the statusCode returned is 0. I tried much modifications to make it work but actually I cannot solve this problem : I tried to subclass NSHTTPURLResponse to force statusCode to 0 => statusCode is never called I tried a category on NSURLResponse which implements statusCode => statusCode is called so I can return 200 but jquery still get a 0 status
So I don't know how to control the final response from the cache to the client, mainly the statusCode and the headers.
If you have any information about this, I might be interested.
If you are interested by the changes I made, the code is :
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
{
request = [SDURLCache canonicalRequestForRequest:request];
NSCachedURLResponse *memoryResponse = [super cachedResponseForRequest:request];
if (memoryResponse)
{
if ([self isConnectedToNetwork])
{
return memoryResponse;
}
else
{
NSURLResponse* response = [[NSURLResponse alloc] initWithURL:request.URL
MIMEType:[[memoryResponse response] MIMEType]
expectedContentLength:[[memoryResponse data] length]
textEncodingName:[[memoryResponse response] textEncodingName]];
NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:[memoryResponse data] userInfo:nil storagePolicy:NSURLCacheStorageAllowedInMemoryOnly];
[response release];
return [cachedResponse autorelease];
}
}
NSString *cacheKey = [SDURLCache cacheKeyForURL:request.URL];
// NOTE: We don't handle expiration here as even staled cache data is necessary for NSURLConnection to handle cache revalidation.
// Staled cache data is also needed for cachePolicies which force the use of the cache.
@synchronized(self.diskCacheInfo)
{
NSMutableDictionary *accesses = [self.diskCacheInfo objectForKey:kSDURLCacheInfoAccessesKey];
if ([accesses objectForKey:cacheKey]) // OPTI: Check for cache-hit in a in-memory dictionnary before to hit the FS
{
NSCachedURLResponse *diskResponse = [NSKeyedUnarchiver unarchiveObjectWithFile:[diskCachePath stringByAppendingPathComponent:cacheKey]];
if (diskResponse)
{
// OPTI: Log the entry last access time for LRU cache eviction algorithm but don't save the dictionary
// on disk now in order to save IO and time
[accesses setObject:[NSDate date] forKey:cacheKey];
diskCacheInfoDirty = YES;
// OPTI: Store the response to memory cache for potential future requests
[super storeCachedResponse:diskResponse forRequest:request];
// SRK: Work around an interesting retainCount bug in CFNetwork on iOS << 3.2.
if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_2)
{
diskResponse = [super cachedResponseForRequest:request];
}
if (diskResponse)
{
if ([self isConnectedToNetwork])
{
return diskResponse;
}
else
{
NSURLResponse* response = [[NSURLResponse alloc] initWithURL:[[diskResponse response] URL]
MIMEType:[[diskResponse response] MIMEType]
expectedContentLength:[[diskResponse data] length]
textEncodingName:[[diskResponse response] textEncodingName]];
NSCachedURLResponse *cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:response data:[diskResponse data] userInfo:nil storagePolicy:NSURLCacheStorageAllowedInMemoryOnly];
[response release];
return [cachedResponse autorelease];
}
}
}
}
}
return nil;
}
Hello, thanks for sharing your solution.
I'm trying to do the same but I'm getting error 301 (permanently moved). Am I missing anything?
I don't know. Try first on a page that you're sure it returns 200 anytime.
Ok, it was all about the ISS server I'm working with. I can't run any AJAX code though. I'll try to work it out but it doesn't seem to be an easy way of getting it done, I'll open a new thread if I find something.
Cheers
Hi dqueffeulouatw
I'm a little bit late here, but I recently had the same problem as you (I was not using SDURLCache) but the task I tried to solve was the same.
After lots of searching I now found a solution, by implementing my own NSURLProtocol subclass, and not using the cache at all. At least for the injection of the local resources. See http://stackoverflow.com/a/9390792/117959 for more information.
cheers