NSCachedURLResponse 忽略 HTTPBody

NSCachedURLResponse ignores HTTPBody

我正在使用此代码创建 NSMutableURLRequest

NSString *urlString = @"http://192.168.1.111/api";
NSURL *url = [NSURL URLWithString:urlString];

NSString *postBody = [NSString stringWithFormat:@"param=%@", param];
NSData *postBodyData = [postBody dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *postBodyLength = [@( postBodyData.length ) stringValue];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

request.URL = url;
request.HTTPMethod = @"POST";
request.HTTPBody = postBodyData;
request.cachePolicy = NSURLRequestUseProtocolCachePolicy;

[request setValue:postBodyLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

和发出请求的代码:

NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];

if (cachedResponse && cachedResponse.data.length > 0) {
    NSError *serializationError = nil;

    id cachedResponseData = [NSJSONSerialization JSONObjectWithData:cachedResponse.data options:0 error:&serializationError];

    if (!serializationError) {
        NSLog(@"WEB: %@:%@ cachedResponseData: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), cachedResponseData);

        [self showTranslations:cachedResponseData forWords:queryStrings withCallback:completion];
    }
} else {
    AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

    requestOperation.responseSerializer = [AFJSONResponseSerializer serializer];

    [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"WEB: %@:%@ responseObject: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"WEB: %@:%@ error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error);
    }];

    [[NSOperationQueue mainQueue] addOperation:requestOperation];
}

如果我首先 运行 它的 param 变量等于 "first",如果经过 else 块并发出请求。在第二个 运行 上,它通过 if 块并从缓存中检索响应数据。但是如果我再次 运行 它并且 param 变量等于 "second",它会再次通过 if 块并从缓存中检索与第一个请求对应的值。我怎样才能让它 像它应该的那样工作 并意识到这是一个不同的请求而不是从缓存中获取它?

AFNetworking 可能在做一些奇怪的事情;我只能告诉您如何使用本机 API 来处理它,因此在您的情况下这可能完全正确,也可能不完全正确。

如果内存可用,操作系统通常不会从缓存中检索 POST 个请求,因为它们不被认为是幂等的。因此,如果您看到缓存,它可能发生在您设备外部的某个地方,例如网络代理。

话虽如此,指定 NSURLRequestReloadIgnoringCacheData 应该可以防止它使用缓存数据。或者您可以通过编写自定义缓存处理回调并返回 nil 而不是 NSCachedURLResponse 对象来阻止它存储在缓存中。

但这里真正的问题是您直接查询缓存而不是让 OS 处理它。缓存没有请求类型或 POST 主体的概念。它只是在查看 URL。如果出于某种原因你真的想缓存 POST 请求,你必须以某种一致的方式连接 URL 和正文数据,然后为修改后的 [= 创建一个新的请求对象20=],并在向缓存添加数据和从缓存检索数据时使用连接的请求对象。