是否可以防止 NSURLRequest 在请求后缓存数据或删除缓存的数据?

Posted

技术标签:

【中文标题】是否可以防止 NSURLRequest 在请求后缓存数据或删除缓存的数据?【英文标题】:Is it possible to prevent an NSURLRequest from caching data or remove cached data following a request? 【发布时间】:2010-09-29 03:24:38 【问题描述】:

在 iPhone 上,我使用 NSURLRequest 对一大块数据执行 HTTP 请求。对象分配高峰,我相应地分配数据。当我完成数据后,我会相应地释放它 - 但是仪器没有显示任何数据已被释放!

我的理论是默认情况下 HTTP 请求会被缓存,但是 - 我不希望我的 iPhone 应用程序缓存这些数据。

有没有办法在请求后清除此缓存或首先防止任何数据被缓存?

我已经尝试使用所有缓存策略,如下所示:

NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
theRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

但似乎没有什么可以释放内存!

【问题讨论】:

会不会与缓存无关?您是否尝试过检查数据以查看应该重新加载的数据是否实际上是旧数据?也许你的韭菜来自其他地方。你如何初始化和释放 NSURLRequests?这可能有助于诊断问题。 仅供参考 - 如果你想通过暴力删除文件,这里有示例代码:salesforce.stackexchange.com/a/69736 【参考方案1】:

通常这样创建请求更容易

NSURLRequest *request = [NSURLRequest requestWithURL:url
      cachePolicy:NSURLRequestReloadIgnoringCacheData
      timeoutInterval:60.0];

然后创建连接

NSURLConnection *conn = [NSURLConnection connectionWithRequest:request
       delegate:self];

并在委托上实现 connection:willCacheResponse: 方法。只需返回 nil 即可。

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse 
  return nil;

【讨论】:

非常感谢您的帮助!尼克。 感谢您的想法 - 我反复调用这样的 SOAP Web 服务,尽管泄漏并未显示任何错误,但它无法控制地增长堆。我优化了几天,最后试图阻止缓存,因为来自内部框架的很多 CFURL* 对象都在闲逛。从 willCacheResponse 返回 nil 是唯一有效的方法! 为什么NSURLRequestReloadIgnoringCacheData都需要实现connection:willCacheResponse: 嗨,我可以用它来加载本地内容吗?以上是针对 NSUrlConnection 但我正在使用 NSUrlRequest 将本地 html 数据加载到 UIWebView 中。我需要拒绝任何缓存,因为有图像从 SQLite 进入 webview,并且内存随着每次页面加载而增加。谢谢。 @fabb,覆盖connection:willCacheResponse: 允许您不将响应存储在缓存中。 NSURLRequestReloadIgnoringCacheData 指定连接应该加载请求而不检查缓存。前者可能有助于管理内存分配。【参考方案2】:

当我从 twitter 请求信息时,我的应用程序中遇到了同样的问题。在我的情况下,我不需要保留这些凭据,所以我使用下一个代码简单地删除它们:

- (void) eraseCredentials
NSURLCredentialStorage *credentialsStorage = [NSURLCredentialStorage sharedCredentialStorage];
NSDictionary *allCredentials = [credentialsStorage allCredentials];

//iterate through all credentials to find the twitter host
for (NSURLProtectionSpace *protectionSpace in allCredentials)
    if ([[protectionSpace host] isEqualToString:@"twitter.com"])
        //to get the twitter's credentials
        NSDictionary *credentials = [credentialsStorage credentialsForProtectionSpace:protectionSpace];
        //iterate through twitter's credentials, and erase them all
        for (NSString *credentialKey in credentials)
            [credentialsStorage removeCredential:[credentials objectForKey:credentialKey] forProtectionSpace:protectionSpace];
    

我希望它适用于某人:)

【讨论】:

这是我的问题的完美解决方案,我有重新登录问题,因为凭据已存储并由 NSURLConnection 自动提交,非常感谢这对我很有帮助:) 感谢它对我有用,我非常感谢您的建议。其实我的问题是 NSURLRequest 存储用户名和密码。因此,这有助于从缓存中删除用户凭据...【参考方案3】:

如果你使用 NSURLConnection 看看委托:

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse

返回值

要存储在缓存中的实际缓存响应。委托可以返回未修改的缓存响应,返回修改后的缓存响应,或者如果不应该为连接存储缓存响应,则返回 nil。

【讨论】:

非常感谢。我的应用程序的内存占用突然减半!尼克。【参考方案4】:

如果您使用NSURLSession,另一个防止请求和参数写入Cache.db ios 的解决方案是在应用程序的Caches 目录中创建,是将会话配置的NSURLCache 设置为0 大小内存和 0 大小磁盘缓存 例如

let configuration = URLSessionConfiguration.default    
configuration.urlCache = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
let session = URLSession(configuration: configuration)

或者如上所述设置在全局缓存级别

URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)

大概是磁盘大小为 0 会阻止 iOS 写入磁盘,但如果您有 reloadIgnoringLocalCacheData 的策略,那么您可能对内存缓存也不感兴趣。

注意这将完全阻止创建任何Caches/Cache.db(请求和响应)或Caches/fsCachedData/ 文件夹(响应数据)。出于安全考虑,我们决定在应用中采用这种方法,因为我们不希望我们的请求永远存储在磁盘缓存中。

如果有人知道有一种方法可以仅停止请求缓存,但保留来自 iOS URL 加载机制的响应数据缓存,我很想知道。 (据我所知,没有关于此的 API 或官方文档)

【讨论】:

你找到这个问题的答案了吗?【参考方案5】:

如果不是特定于单个请求(您希望禁用整个应用程序的缓存),则最好选择以下一个。将此代码添加到应用程序委托中或根据您的需要添加到任何地方

        int cacheSizeMemory = 0; // 0MB
        int cacheSizeDisk = 0; // 0MB
        NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
        [NSURLCache setSharedURLCache:sharedCache];

【讨论】:

对我来说很好用,但你可以只使用 0 而不是做乘法,反正结果是 0。【参考方案6】:
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] url];
[request setValue:@"no-store" forHTTPHeaderField:@"Cache-Control"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

假设服务器正确实现,将Cache-Control:no-store 头放入请求中会生成具有相同头的服务器响应,从而导致NSURLCache 不会将响应数据存储在磁盘上。

因此,无需使用猎枪方法禁用NSURLCache 磁盘缓存。

PS:添加标头应该适用于所有 HTTP 框架,例如 AFNetworking

【讨论】:

以上是关于是否可以防止 NSURLRequest 在请求后缓存数据或删除缓存的数据?的主要内容,如果未能解决你的问题,请参考以下文章

ios开发防止App被抓包

iphone:在 NSURLRequest 期间未调用 applicationWillTerminate?

如何使用 AFNetorking 和 NSURLRequest 发出 HTTP 请求?

NSURLRequest setTimeoutInterval 没有按预期工作

IOS NSURLRequest 设置 Header

Alamofire 请求和自定义 NSURLRequest 的区别