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 请求

NSURLConnection 是不是保留其委托?

NSURLConnection 是不是阻塞 Main/UI 线程

iOS开发系列-NSURLSession

IOS NSURLConnection(大文件下载)

NSURLConnection 返回错误而不是响应 401