AFNetworking 2.0 - 强制缓存

Posted

技术标签:

【中文标题】AFNetworking 2.0 - 强制缓存【英文标题】:AFNetworking 2.0 - Forced caching 【发布时间】:2014-08-30 19:59:28 【问题描述】:

如果不包含ExpiresCache-Control: max-age,是否可以强制响应缓存?

我遇到过this 文章,但不幸的是URLSession:dataTask:willCacheResponse:completionHandler: 从未在我的AFHTTPSessionManager 子类中被调用。

任何帮助表示赞赏。

【问题讨论】:

可以使用NSMutableURLRequestcachePolicy属性。 【参考方案1】:

您可以通过实现自己的不遵循标准 HTTP 缓存规则的 NSURLProtocol 来强制缓存。一个complete tutorial is here,它使用Core Data对数据进行持久化,但基本步骤是:

子类NSURLProtocol+registerClass:注册你的子类 如果这是您第一次看到request,则在您的+canInitWithRequest: 方法中返回YES,如果不是,则返回NO

你现在有两个选择:

    实现您自己的缓存存储(在这种情况下,请按照上面链接的教程进行操作) 注入您希望 URL 加载系统遵循的缓存控制标头

假设您想要 #2,在您的协议子类中覆盖 connection:didReceiveResponse: 以创建一个包含您想要模拟的缓存控制标头的响应:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response 
    // Create a dictionary with the headers you want
    NSMutableDictionary *newHeaders = [response.allHeaderFields mutableCopy];
    newHeaders[@"Cache-Control"] = @"no-transform,public,max-age=300,s-maxage=900";

    // Create a new response
    NSHTTPURLResponse *newResponse = [[NSHTTPURLResponse alloc] initWithURL:response.URL
                                                                 statusCode:response.statusCode
                                                                HTTPVersion:@"HTTP/1.1"
                                                               headerFields:newHeaders];


    [self.client URLProtocol:self
          didReceiveResponse:newResponse
          cacheStoragePolicy:NSURLCacheStorageAllowed];

这将导致响应被缓存,就好像服务器提供了这些标头一样。


仅适用于 URL 会话,您需要设置会话配置的 protocolClasses。由于您使用的是 AFNetworking,因此看起来像:

[AFHTTPSessionManager sharedManager].session.configuration.protocolClasses = @[[MyURLProtocol class]]

有一些警告,所以请确保你read the protocolClasses documentation。


一些注意事项:

如果有任何方法可以通过让您的服务器发送适当的标头来解决此问题,请改为这样做。 为简洁起见,我硬编码了“HTTP/1.1”,但从技术上讲,您应该将其从响应中提取出来。 AFNetworking 使用标准的 URL 加载系统,与此问题几乎无关。

【讨论】:

非常感谢!刚回到城里,明天会深入研究,然后奖励你。 @BenW Cool,如果您有任何问题,请告诉我。 这一切都设置好了,但由于某种原因,即使我从 canInitWithRequest 返回 YES,我的 NSURLProtocol 子类也不会调用 startLoading。加载图像时将调用这两种方法,但将请求加载到我的 api 时不会调用 startLoading。见过吗? 我应该提到我首先在 didFinishLoadingWithOptions 中注册它,所以它应该具有优先权,我找不到任何其他注册的 url 协议。 @BenW 是否调用了canInitWithRequest:?如果是,并且您从中返回YES,则应调用startLoading。如果不是,您是否在提出任何请求之前使用registerClass: 注册了子类?

以上是关于AFNetworking 2.0 - 强制缓存的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 2.0 上的缓存

缓存图像,使其不会在 reloadData 调用时重新加载 - AFNetworking 2.0 setImageWithUrl

用于 POST 的 AFNetworking 2.0 自定义标头

从 AFNetworking 1.3 迁移到 AFNetworking 2.0 的问题

AFNetworking 2.0 JSON 解析

AFNetworking 2.0 对现有项目的更新