Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache in offline #18

Open
dqueffeulouatw opened this issue Sep 8, 2011 · 4 comments
Open

Cache in offline #18

dqueffeulouatw opened this issue Sep 8, 2011 · 4 comments

Comments

@dqueffeulouatw
Copy link

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;
}
@ale0xb
Copy link

ale0xb commented Oct 26, 2011

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?

@dqueffeulouatw
Copy link
Author

I don't know.
Try first on a page that you're sure it returns 200 anytime.

@ale0xb
Copy link

ale0xb commented Oct 28, 2011

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

@vkodocha
Copy link

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

jkubicek referenced this issue in smule/SDURLCache Nov 8, 2012
…hods

Don't mix non-keyed archiver methods with keyed archiver methods.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants