Objective c 从未调用AFHTTPSessionManager上setDataTaskWillCacheResponseBlock设置的块

Objective c 从未调用AFHTTPSessionManager上setDataTaskWillCacheResponseBlock设置的块,objective-c,caching,afnetworking,Objective C,Caching,Afnetworking,我开发了一个应用程序,它严重依赖AFNetworking将数据从私有API加载到Mantle模型中。我的API客户端是AFHTTPSessionManager的一个子类 我正试图通过利用NSURLCache实现基本的脱机模式。如果AFNetworkReachabilityManager表示网络不可访问,则该方法是将dataTaskWithRequest:completionHandler上的请求缓存策略修改为NSURLRequestReturnCacheDataDontLoad 虽然我可以通过在

我开发了一个应用程序,它严重依赖AFNetworking将数据从私有API加载到Mantle模型中。我的API客户端是
AFHTTPSessionManager
的一个子类

我正试图通过利用
NSURLCache
实现基本的脱机模式。如果
AFNetworkReachabilityManager
表示网络不可访问,则该方法是将
dataTaskWithRequest:completionHandler
上的请求缓存策略修改为
NSURLRequestReturnCacheDataDontLoad

虽然我可以通过在测试期间使用断点来验证这是否确实有效,但请求本身并没有被缓存。我通过从Xcode下载应用程序容器并检查Cache.db sqlite文件(该文件为空)来验证这一点。我还通过手动创建一个虚拟的
NSCachedURLResponse
并使用
storeCachedResponse:forRequest
将其强制存储在缓存中,验证了我正在查看正确的缓存。然后虚拟响应确实显示在Cache.db sqlite文件中

所以,我想我把问题缩小到了我的“常规”响应没有被缓存。我还可以修改服务器API发送的头。我打算在这里做的是在API响应上设置一个头
缓存控制:private
(这样就不会使使用此API缓存的其他客户端响应它们不应该的响应),并在
setDataTaskWillCacheResponseBlock
块中修改此缓存头,但此块永远不会触发

我知道URL系统可能会决定何时调用
URLSession:dataTask:willCacheResponse:completionHandler
,它根据一些未记录的规则调用块,主要是存在
缓存控制
头,以及响应大小/缓存大小比率。但是我的响应是一个145字节的JSON,并且设置了
缓存控制
头(我通过
curl-v
和检查我请求的
success
块的
task
参数进行了验证)

我还尝试了一个更具攻击性的缓存头,
cache-Control:public,max-age=2592000
,以查看它是否缓存响应或至少调用块,但行为完全相同。我还检查了
myAFHTTPSessionManagerSubclass.session.delegate
属性,它确实指向
myafhttpsessionanagerSubclass
,如预期

我还尝试在我的子类中直接重写
URLSession:dataTask:willCacheResponse:completionHandler
,但它仍然没有被调用。在
Pods
目录中的
AFURLSessionManager.m
上的同一委托方法上设置断点也不起作用,在断点上执行从未停止

根据我的
Podfile.lock
文件,我正在使用AFNetworking的2.5.4版

那么,如何使我的响应缓存(最好不要在响应上设置快速缓存策略),以便我可以在我的应用程序中实现快速脱机模式?

编辑:我还尝试创建一个
NSURLSession
,看看这是否可行。因此,我创建了一个简单的Node.js服务器,它只回答一些简单的问题并设置缓存头:

$ curl -v http://192.168.1.107:1337/
* Hostname was NOT found in DNS cache
*   Trying 192.168.1.107...
* Connected to 192.168.1.107 (192.168.1.107) port 1337 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.37.1
> Host: 192.168.1.107:1337
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Cache-Control: public
< Date: Thu, 11 Jun 2015 14:38:14 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
Hello World
响应已正确打印,但从未调用
willCacheResponse
(我设置了断点)。我再次尝试检查容器,创建了
mytestcache
目录,但该目录为空。我还尝试了
缓存控制:max age=86400
,结果相同


(交叉发布到AFNetworking issues网站:)

好吧,我会让你惊讶的-你上面写的代码运行得很好,…但它不适合你想要实现的目标;)

原因很简单-当您通过方法
dataTaskWithRequest:completionHandler:
创建请求时,不会调用委托方法。您需要使用方法
dataTaskWithRequest:

-先阅读注释

第二件事是,当我们谈论缓存时,NSURLSession实际上是sux。在iOS 7.x/8.x中,您可能会遇到几个问题。当我在我的应用程序中实现自定义缓存时,我遇到了这样的噩梦,它最终与NSURLCache毫无共同之处。我还决定创建基于NSURLSession和AFNetworking的框架

iOS 7上的一个问题是使用
defaultConfiguration
创建
NSURLSession
NSURLCache
对象将不同于全局对象-非常意外的行为。 iOS 8上的一个问题是POST请求也被缓存,这可能会影响应用程序的安全性。顺便说一句

也许它不能回答您的问题,但您应该意识到iOS版本之间的奇怪行为和差异。 老实说,我建议您使用AFHTTPRequestOperationManager而不是AFHTTPSessionManager,因为至少NSURLConnection与NSURLCache的工作原理类似:)

- (void)viewDidLoad {
    [super viewDidLoad];

    // Prime the cache
    [NSURLCache setSharedURLCache:[[NSURLCache alloc] initWithMemoryCapacity:2*1024 diskCapacity:10*1024*1024 diskPath:@"mytestcache"]];
    // The sleep is to be absolutely sure the cache did initialise
    sleep(2);

    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
    [[session dataTaskWithURL:[NSURL URLWithString:@"http://192.168.1.107:1337"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSLog(@"Got response: %@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
    }] resume];
}

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse *))completionHandler {

    completionHandler(proposedResponse);
}