我找不到任何问题的答案,可能是我错过了什么......
当我请求一个 url 时,我需要知道响应是来自缓存还是来自网络。
状态码是 304 还是 200 ?(但AFNetworking
总是响应 200)
我ASIHTTPRequest
曾经检查“ didUseCachedResponse
” from ASIHTTPRequest
,这是完美的。
我找不到任何问题的答案,可能是我错过了什么......
当我请求一个 url 时,我需要知道响应是来自缓存还是来自网络。
状态码是 304 还是 200 ?(但AFNetworking
总是响应 200)
我ASIHTTPRequest
曾经检查“ didUseCachedResponse
” from ASIHTTPRequest
,这是完美的。
我想我找到了一个解决方案来确定响应是从缓存返回还是不使用 AFNetworking 2.0。我发现每次从服务器返回一个新响应(状态 200,而不是 304)时,都会调用cacheResponseBlock
它的一个属性。AFHTTPRequestOperation
如果应该缓存响应,则该块应该返回NSCachedURLResponse
,如果不应该缓存,则返回 nil。这样您就可以过滤响应并仅缓存其中的一些。在这种情况下,我正在缓存来自服务器的所有响应。诀窍是,当服务器发送 304 并从缓存加载响应时,不会调用此块。所以,这是我正在使用的代码:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
BOOL __block responseFromCache = YES; // yes by default
void (^requestSuccessBlock)(AFHTTPRequestOperation *operation, id responseObject) = ^(AFHTTPRequestOperation *operation, id responseObject) {
if (responseFromCache) {
// response was returned from cache
NSLog(@"RESPONSE FROM CACHE: %@", responseObject);
}
else {
// response was returned from the server, not from cache
NSLog(@"RESPONSE: %@", responseObject);
}
};
void (^requestFailureBlock)(AFHTTPRequestOperation *operation, NSError *error) = ^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"ERROR: %@", error);
};
AFHTTPRequestOperation *operation = [manager GET:@"http://example.com/"
parameters:nil
success:requestSuccessBlock
failure:requestFailureBlock];
[operation setCacheResponseBlock:^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
// this will be called whenever server returns status code 200, not 304
responseFromCache = NO;
return cachedResponse;
}];
这个解决方案对我有用,到目前为止我还没有发现任何问题。但是,如果您有更好的想法或对我的解决方案有异议,请随时发表评论!
似乎苹果不想让你知道它是否来自缓存。
我找到了一种方法,将修改日期与请求关联起来,并在 AFNetWorking 回复我时比较这个日期。
没有我想要的那么干净,但可以工作......
在 AFNetworking 中有一种方法可以指定应该被视为成功的状态码,它是通过响应序列化来完成的,这里是代码
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
AFHTTPResponseSerializer *respSerializer = [AFHTTPResponseSerializer serializer];
NSMutableIndexSet *responseCodes = [NSMutableIndexSet indexSet];
[responseCodes addIndex:200];
[responseCodes addIndex:304];
[operation setResponseSerializer:respSerializer];
使用此代码,AFNetworking 会将 304 视为成功
创建您的 URLCache 类并覆盖storeCachedResponse方法
class MyURLCache: URLCache {
override func storeCachedResponse(_ cachedResponse: CachedURLResponse, for request: URLRequest) {
//adding caching header if needed
var headers = response.allHeaderFields
headers.removeValue(forKey: "Cache-Control")
headers["Cache-Control"] = "max-age=\(5 * 60)" //5 min
//the trick
if (headers["isCachedReponse"] == nil){
headers["isCachedReponse"] = "true"
}
if let
headers = headers as? [String: String],
let newHTTPURLResponse = HTTPURLResponse(url: response.url!, statusCode: response.statusCode, httpVersion: "HTTP/1.1", headerFields: headers) {
let newCachedResponse = CachedURLResponse(response: newHTTPURLResponse, data: cachedResponse.data)
super.storeCachedResponse(newCachedResponse, for: request)
}
}
}
在 AppDelegate 中使用您的 URLCache 设置 URLCache.shared
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let cache = MyURLCache(memoryCapacity: 1024 * 1024 * 500, diskCapacity: 1024 * 1024 * 500, diskPath: nil)
URLCache.shared = cache
return true
}
}
在响应回调中检查响应内容的标题是否为“newResponse”键
if (response.allHeaderFields["isCachedReponse"] == nil){
print("not cache")
} else {
print("cache")
}
适用于所有版本的AFNetworking