我找不到任何问题的答案,可能是我错过了什么......
当我请求一个 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