【问题标题】:Does NSURLConnection take advantage of NSURLCache?NSURLConnection 是否利用了 NSURLCache?
【发布时间】:2009-12-08 21:35:12
【问题描述】:

我正在尝试弄清楚如何使用 URL 加载框架来加载利用缓存的 URL。

我正在使用 NSURLConnections 并为它们提供 NSURLRequests。我什至将这些请求上的 cachePolicy 设置为 NSURLRequestReturnCacheDataElseLoad。第一次加载请求时,它会自动放入缓存中([NSURLCache sharedCache] 有)。但是下次我加载相同的请求时,NSURLConnection 似乎会忽略缓存中的内容并重新加载数据。

我是否应该手动实现缓存查找并返回缓存数据? NSURLConnection 不这样做吗?或者有什么方法可以让框架无缝使用缓存?

更新:尝试了以下但没有成功:

  • 将请求缓存策略设置为NSURLRequestReturnCacheDataElseLoad 而不是NSURLRequestUseProtocolCachePolicy
  • 重复使用请求对象而不是创建一个新对象
  • 使用+[NSURLConnection sendSynchronousRequest:returningResponse:error:] 而不是异步加载

【问题讨论】:

  • 你给他们提供相同的 NSURLRequest 对象吗?文档指出 NSURLCache 通过将特定的 NSURLRequest 对象映射到指定的响应数据来工作,因此即使您向同一个 URL 发出请求,它仍然可能导致缓存未命中。
  • 它从哪里请求数据?它是静态页面还是带有适当 HTTP 标头的动态页面?也许 Expires、If-Modified-Since 或 Cache-Control 标头覆盖了缓存?
  • 不,我正在创建一个新的 NSURLRequest。但是当我用那个新的请求对象做[[NSURLCache sharedURLCache] cachedResponseForRequest:] 时,会有一个缓存的响应。所以 NSURLCache 不知何故知道请求是相同的。
  • PS:我尝试重用 NSURLRequest 对象。没什么区别。
  • 好主意。我已经尝试过静态和动态,似乎没有什么不同。看不到您在请求或响应中提到的任何标头。

标签: iphone nsurlconnection nsurlrequest


【解决方案1】:

注意 iOS 5 及更高版本提供了一个 sharedURLCache,它具有内存和磁盘容量。

除非您将 NSURLCache 设置为具有一定容量,否则不会缓存任何内容:

// A 10MB cache. This a good avatar-image-cache size but might be too 
// large for your app's memory requirements. YMMV.
[[NSURLCache sharedURLCache] setMemoryCapacity:1024*1024*10];

默认的 iPhone NSURLCache 实例拒绝缓存到磁盘。如果你需要这种行为,你必须继承 NSURLCache 并实现你自己的磁盘缓存。我在 GitHub 上找到了许多磁盘缓存的示例,但恕我直言,它们都没有完成完全必要的“修剪”步骤。

【讨论】:

  • 看来 [[NSURLCache sharedURLCache] setMemoryCapacity:1024*1024*10] 有效,但每次发出请求时都必须调用它,因为当我在 AppDelegate 中调用它一次时,缓存行为是应用程序启动之间完全随机(有时有效,有时无效)。
  • 即使你没有明确设置缓存,NSURLCache 仍然会创建一个 db 文件并保存内容!
  • @Abhinit 是的,我的回答早于 iOS 5。从那时起,除非您禁用它,否则始终会设置缓存。
【解决方案2】:

它确实会自动使用 NSURLCache,至少在某些情况下是这样。当然它在以下代码中:

编辑 - 适用于 OS X 10.6 Cocoa 应用程序,而不是 iPhone(误读问题)

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {

    // run request with default cache policy
 NSMutableURLRequest *req=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://en.wikipedia.org/"]];
 NSData *data=[NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil];
 NSLog(@"Received %d bytes", [data length]);

 sleep(10);

    // now run it asking it to use the cache
 [req setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
 data=[NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil];
 NSLog(@"Received %d bytes", [data length]);

    return 0;
}

【讨论】:

  • 很有趣,谢谢。不过,对于它的价值,我正在执行异步请求——不确定这是否重要。
  • 好的,所以我真的试过了,但它不适合我。第二个请求仍然需要几百毫秒,如果我使用缓存策略NSURLRequestReturnCacheDataDontLoad,它会返回 0 个字节。此外,如果我在使用[[NSURLCache sharedURLCache] cachedResponseForRequest:req] 之间直接查询缓存,它会返回 nil。所以对我来说这里没有缓存。我在 iPhone 模拟器中运行,在 Snow Leopard 下模拟 OS 3.0(也尝试过 3.1.2)。
  • 对,可能与我只是直接在 OS X 下运行有关。我没有发现 iphone 标签 - 抱歉。
【解决方案3】:

您是否尝试过使用connection:willCacheResponse: 方法?根据URL Loading System documentation,“默认情况下,连接的数据根据​​处理请求的 NSURLProtocol 子类提供的支持进行缓存。NSURLConnection 委托可以通过实现 connection:willCacheResponse: 来进一步细化该行为。”

【讨论】:

  • 是的,我已经尝试实现connection:willCacheResponse:--没有帮助。该方法确实被调用了,而且——这是踢球者——响应肯定会在缓存中结束。在第一次请求之后,[[NSURLCache sharedCache] cachedResponseForRequest:request] 返回缓存的响应。但是,如果我随后用相同的请求初始化一个 NSURLConnection,它会重新获取而不是访问缓存。
  • 我知道过去我实际上已经查看了缓存,这很有帮助——尽管在那种特殊情况下,我希望方法立即返回,而不是尽可能地异步加载。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 2013-04-23
  • 1970-01-01
  • 2017-06-06
  • 2015-12-12
相关资源
最近更新 更多