Bypassing http response header Cache-Control: how to set cache expiration?

后端 未结 3 708
面向向阳花
面向向阳花 2020-12-25 08:56

All http responses from a server come with the headers that inform our app not to cache the responses:

Cache-Control: no-cache
Pragma: no-cache
Expires: 0
         


        
3条回答
  •  心在旅途
    2020-12-25 09:09

    You can implement a custom NSURLCache that only returns cached responses that has not expired.

    Example:

    #import "CustomURLCache.h"
    
    NSString * const EXPIRES_KEY = @"cache date";
    int const CACHE_EXPIRES = -10;
    
    @implementation CustomURLCache
    
    // static method for activating this custom cache
    +(void)activate {
        CustomURLCache *urlCache = [[CustomURLCache alloc] initWithMemoryCapacity:(2*1024*1024) diskCapacity:(2*1024*1024) diskPath:nil] ;
        [NSURLCache setSharedURLCache:urlCache];
    }
    
    -(NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
        NSCachedURLResponse * cachedResponse = [super cachedResponseForRequest:request];
        if (cachedResponse) {
            NSDate* cacheDate = [[cachedResponse userInfo] objectForKey:EXPIRES_KEY];
            if ([cacheDate timeIntervalSinceNow] < CACHE_EXPIRES) {
                [self removeCachedResponseForRequest:request];
                cachedResponse = nil;
            }
        }
    
        return cachedResponse;
    }
    
    - (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request {
        NSMutableDictionary *userInfo = cachedResponse.userInfo ? [cachedResponse.userInfo mutableCopy] : [NSMutableDictionary dictionary];
        [userInfo setObject:[NSDate date] forKey:EXPIRES_KEY];
        NSCachedURLResponse *newCachedResponse = [[NSCachedURLResponse alloc] initWithResponse:cachedResponse.response data:cachedResponse.data userInfo:userInfo storagePolicy:cachedResponse.storagePolicy];
    
        [super storeCachedResponse:newCachedResponse forRequest:request];
    }
    
    @end
    

    If this does not give you enough control then I would implement a custom NSURLProtocol with a startLoading method as below and use it in conjunction with the custom cache.

    - (void)startLoading
    {
        NSMutableURLRequest *newRequest = [self.request mutableCopy];
        [NSURLProtocol setProperty:@YES forKey:@"CacheSet" inRequest:newRequest];
    
        NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:self.request];
        if (cachedResponse) {  
            [self connection:nil didReceiveResponse:[cachedResponse response]];
            [self connection:nil didReceiveData:[cachedResponse data]];
            [self connectionDidFinishLoading:nil];
        } else {
            _connection = [NSURLConnection connectionWithRequest:newRequest delegate:self];
        }
    }
    

    Some links:

    • Useful info on NSURLCache
    • Creating a custom NSURLProtocol

提交回复
热议问题