NSURLConnection 是不是利用了 NSURLCache?
Posted
技术标签:
【中文标题】NSURLConnection 是不是利用了 NSURLCache?【英文标题】: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 对象。没什么区别。
好主意。我已经尝试过静态和动态,似乎没有什么不同。看不到您在请求或响应中提到的任何标头。
【参考方案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,它会重新获取而不是访问缓存。
我知道过去我实际上已经查看了缓存,这很有帮助——尽管在那种特殊情况下,我希望方法立即返回,而不是尽可能地异步加载。以上是关于NSURLConnection 是不是利用了 NSURLCache?的主要内容,如果未能解决你的问题,请参考以下文章
NSURLConnection 发送 GET 请求而不是 POST 请求