I am using Olivier Poitrey's SDURLCache (github link) as an alternative to NSURLCache
to enable disk-caching in an iPhone app.
It works very well but is curiously leaking a NSHTTPURLResponseInternal
when a disk cached object is returned (no leak when object is returned from memory or no object found). The following code snippet shows how SDURLCache reads the data from the disk:
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
{
NSCachedURLResponse *memoryResponse = [super cachedResponseForRequest:request];
if (memoryResponse)
{
return memoryResponse;
}
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.
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];
return diskResponse;
}
}
return nil;
}
The stack trace for each of the NSHTTPURLResponseInternal
leaks contains two references to the SDURLCache
code.
The first points to the line [accesses setObject:[NSDate date] forKey:cacheKey];
. The second, and latest points to the following:
@implementation NSCachedURLResponse(NSCoder)
- (id)initWithCoder:(NSCoder *)coder
{
return [self initWithResponse:[coder decodeObjectForKey:@"response"]
data:[coder decodeDataObject]
userInfo:[coder decodeObjectForKey:@"userInfo"]
storagePolicy:[coder decodeIntForKey:@"storagePolicy"]];
}
@end
Has anyone encountered this problem before? Any thoughts on a solution? Let me know if I should post more code samples.
Cheers.
UPDATE: Tweet from Olivier Poitrey, the author of the code
I'm planning on removing the NSURLCache inherency and handle the memory cache, it may fix the leak
Not an answer per se, but rather, awareness. NSURLCache on iOS 5.0 and above now caches to both flash and RAM by default. Thus, if you were using SDURLCache in order to obtain on-disk caching, and are targeting 5.0 and above, then there's no reason to use SDURLCache.