views:

209

answers:

1

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