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