簡體   English   中英

如何設置NSURLRequest緩存過期?

[英]How to set NSURLRequest cache expiration?

我正在使用AFNetworking並且需要在一個響應中緩存數據幾分鍾。 所以我在app delegate中設置了NSUrlCache,然后在我的請求中設置它:

NSMutableURLRequest *request = //obtain request; 
request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;

然后如何設置到期日期:如果數據加載超過n分鍾前,請求服務器而不是磁盤響應?

編輯:

假設服務器不支持緩存,我需要在代碼中管理它。

所以,我找到了解決方案。

想法是使用connection:willCacheResponse:方法。 在緩存響應之前,它將被執行,在那里我們可以更改響應並返回new,或者返回nil,並且不會緩存響應。 當我使用AFNetworking時,有一個很好的方法:

- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block;

添加代碼:

  [operation setCacheResponseBlock:^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
    if([connection currentRequest].cachePolicy == NSURLRequestUseProtocolCachePolicy) {
      cachedResponse = [cachedResponse responseWithExpirationDuration:60];
    }
    return cachedResponse;
  }];

來自類別的responseWithExpirationDuration

@interface NSCachedURLResponse (Expiration)
-(NSCachedURLResponse*)responseWithExpirationDuration:(int)duration;
@end

@implementation NSCachedURLResponse (Expiration)

-(NSCachedURLResponse*)responseWithExpirationDuration:(int)duration {
  NSCachedURLResponse* cachedResponse = self;
  NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)[cachedResponse response];
  NSDictionary *headers = [httpResponse allHeaderFields];
  NSMutableDictionary* newHeaders = [headers mutableCopy];

  newHeaders[@"Cache-Control"] = [NSString stringWithFormat:@"max-age=%i", duration];
  [newHeaders removeObjectForKey:@"Expires"];
  [newHeaders removeObjectForKey:@"s-maxage"];

  NSHTTPURLResponse* newResponse = [[NSHTTPURLResponse alloc] initWithURL:httpResponse.URL
                                                               statusCode:httpResponse.statusCode
                                                              HTTPVersion:@"HTTP/1.1"
                                                             headerFields:newHeaders];

  cachedResponse = [[NSCachedURLResponse alloc] initWithResponse:newResponse
                                                            data:[cachedResponse.data mutableCopy]
                                                        userInfo:newHeaders
                                                   storagePolicy:cachedResponse.storagePolicy];
  return cachedResponse;
}

@end

因此,我們根據http / 1.1在http標頭中設置以秒為單位的到期。為此我們需要設置一個標頭:Expires,Cache-Control:s-maxage或max-age然后創建新的緩存響應,因為屬性是只讀,並返回新對象。

Swift相當於@ HotJard使用URLSession的解決方案

extension CachedURLResponse {
    func response(withExpirationDuration duration: Int) -> CachedURLResponse {
        var cachedResponse = self
        if let httpResponse = cachedResponse.response as? HTTPURLResponse, var headers = httpResponse.allHeaderFields as? [String : String], let url = httpResponse.url{

            headers["Cache-Control"] = "max-age=\(duration)"
            headers.removeValue(forKey: "Expires")
            headers.removeValue(forKey: "s-maxage")

            if let newResponse = HTTPURLResponse(url: url, statusCode: httpResponse.statusCode, httpVersion: "HTTP/1.1", headerFields: headers) {
            cachedResponse = CachedURLResponse(response: newResponse, data: cachedResponse.data, userInfo: headers, storagePolicy: cachedResponse.storagePolicy)
            }
        }
        return cachedResponse
    }
}

然后在自定義類中實現URLSessionDataDelegate協議

func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void) {

    if dataTask.currentRequest?.cachePolicy == .useProtocolCachePolicy {
        let newResponse = proposedResponse.response(withExpirationDuration: 60)
        completionHandler(newResponse)
    }else {
        completionHandler(proposedResponse)
    }
}

不要忘記創建配置和會話,將自定義類作為委托引用傳遞,例如

let session = URLSession(
        configuration: URLSession.shared.configuration,
        delegate: *delegateReference*,
        delegateQueue: URLSession.shared.delegateQueue
    )
let task = session.dataTask(with: request)
task.resume()

NSURLCache的響應到期是通過HTTP響應中的Cache-Control標頭Cache-Control

編輯我看到你已經更新了你的問題。 如果服務器未在響應中提供Cache-Control標頭,則不會緩存它。 對該端點的每個請求都將加載端點,而不是返回緩存的響應。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM