SDURLCache with AFNetworking and offline mode not working

前端 未结 3 1767
情深已故
情深已故 2020-12-23 13:13

I\'m using AFNetworking and SDURLCache for all my networking operations.

I have SDURLCache set like this:

SDUR         


        
相关标签:
3条回答
  • 2020-12-23 13:31

    It sounds like you want the request to succeed, even though the cache says the data has expired and should be retrieved from the server. You may have some luck setting the cache policy (different policy for online vs. offline) of certain requests where you'd rather use stale data than fail.

    NSMutableURLRequest -> setCachePolicy

    It looks like NSURLRequestReturnCacheDataDontLoad is the policy you want for offline mode.

    Hope that helps!

    0 讨论(0)
  • 2020-12-23 13:35

    Well I've finally reached a not so ugly workaround:

    First

    If you're using IOS5/IOS6 you can drop SDURLCache and use the native one:

    //Set Cache
    NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
                                                         diskCapacity:20 * 1024 * 1024
                                                             diskPath:nil];
    [NSURLCache setSharedURLCache:URLCache];
    

    But remember that in IOS5 https requests wont be cached in IOS6 they will.

    Second

    We need to add the following frameworks to our Prefix.pch so AFNetworking can start monitoring our internet connection.

    #import <MobileCoreServices/MobileCoreServices.h>
    #import <SystemConfiguration/SystemConfiguration.h>
    

    Third

    We need and AFHTTPClient instance so we can intercept every outgoing request and change his cachePolicy

    -(NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters {
    
        NSMutableURLRequest * request = [super requestWithMethod:method path:path parameters:parameters];
        if (request.cachePolicy == NSURLRequestUseProtocolCachePolicy && self.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) {
            request.cachePolicy = NSURLRequestReturnCacheDataDontLoad;
        }
    
        if (self.networkReachabilityStatus == AFNetworkReachabilityStatusUnknown) {
    
            puts("uknown reachability status");
        }
    
        return request;
    }
    

    With these peaces of code we can now detect when the wifi/3g is unavailable and the specify the request to use always the cache no matter what. (Offline Mode)

    Notes

    • I still don't know what to do when the networkReachabilityStatus is AFNetworkReachabilityStatusUnknown This can happen is a request is made as soon as the application starts and AF has not obtained the internet status yet.

    • Remember that in order for this to work the server has to set the correct cache headers in the http response.

    UPDATE

    Looks like IOS6 has some problems loading cached responses in no-internet situations, so even if the request is cached and the request cache policy is seted to NSURLRequestReturnCacheDataDontLoad the request will fail.

    So an ugly workaround is to modify (void)connection:(NSURLConnection __unused *)connection didFailWithError:(NSError *)error in AFURLConnectionOperation.m to retrieve the cached response if the request fails but only for specific cache policies.

    - (void)connection:(NSURLConnection __unused *)connection
      didFailWithError:(NSError *)error
    {
        self.error = error;
    
        [self.outputStream close];
    
        [self finish];
    
        self.connection = nil;
    
        //Ugly hack for making the request succeed if we can find a valid non-empty cached request
        //This is because IOS6 is not handling cache responses right when we are in a no-connection sittuation
        //Only use this code for cache policies that are supposed to listen to cache regarding it's expiration date
        if (self.request.cachePolicy == NSURLRequestUseProtocolCachePolicy ||
            self.request.cachePolicy == NSURLRequestReturnCacheDataElseLoad ||
            self.request.cachePolicy == NSURLRequestReturnCacheDataDontLoad) {
    
            NSCachedURLResponse * cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:self.request];
            if (cachedResponse.data.length > 0) {
                self.responseData = cachedResponse.data;
                self.response = cachedResponse.response;
                self.error = nil;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-23 13:45

    Can't tell much without your HTTP headers -- but the most common reason for this is NSURLProtocol forcing revalidation before delivering cached response to WebView.

    Please take a look here : http://robnapier.net/blog/offline-uiwebview-nsurlprotocol-588

    0 讨论(0)
提交回复
热议问题