Hot*_*ard 12 caching objective-c ios
我正在使用AFNetworking并且需要在一个响应中缓存数据几分钟.所以我在app delegate中设置了NSUrlCache,然后在我的请求中设置它:
NSMutableURLRequest *request = //obtain request;
request.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
Run Code Online (Sandbox Code Playgroud)
然后如何设置到期日期:如果数据加载时间超过n分钟,请询问服务器响应而不是磁盘响应?
编辑:
假设服务器不支持缓存,我需要在代码中管理它.
Hot*_*ard 16
所以,我找到了解决方案.
想法是使用connection:willCacheResponse:方法.在缓存响应之前,它将被执行,在那里我们可以更改响应并返回new,或者返回nil,并且不会缓存响应.当我使用AFNetworking时,有一个很好的方法:
- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block;
Run Code Online (Sandbox Code Playgroud)
添加代码:
[operation setCacheResponseBlock:^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
if([connection currentRequest].cachePolicy == NSURLRequestUseProtocolCachePolicy) {
cachedResponse = [cachedResponse responseWithExpirationDuration:60];
}
return cachedResponse;
}];
Run Code Online (Sandbox Code Playgroud)
其中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
Run Code Online (Sandbox Code Playgroud)
因此,我们根据http/1.1在http标头中设置以秒为单位的到期. 为此我们需要设置一个标头:Expires,Cache-Control:s-maxage或max-age然后创建新的缓存响应,因为属性是只读,并返回新对象.
Swift相当于使用URLSession的@HotJard解决方案
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
}
}
Run Code Online (Sandbox Code Playgroud)
然后在您的自定义类中实现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)
}
}
Run Code Online (Sandbox Code Playgroud)
不要忘记创建您的配置和会话,将您的自定义类作为委托引用进行传递,例如
let session = URLSession(
configuration: URLSession.shared.configuration,
delegate: *delegateReference*,
delegateQueue: URLSession.shared.delegateQueue
)
let task = session.dataTask(with: request)
task.resume()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6600 次 |
| 最近记录: |