【问题标题】:How to handle a few thousand NSURLConnection requests, download images and keep the memory usage down如何处理几千个 NSURLConnection 请求、下载图像并降低内存使用量
【发布时间】:2012-03-14 02:37:08
【问题描述】:

我正在开发一个下载资源并将其写入磁盘以供以后离线使用的应用程序,它始终是自定义内容。目前,我们正在处理大约 4000 个 JPG 的内容。用户初始化将内容下载到 iPad 上,并且 UI 中有一个进度条,因此用户基本上会等到完成。问题是分配了大约 180 - 190 MB 的内存,它崩溃了。

我在 Instruments 中看到的是 CFData (store) 是罪魁祸首,我的理解是 CFData (store) 是 NSURLConnection 请求的缓存。

我试过了:

NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];

[[NSURLCache sharedURLCache] removeAllCachedResponses];

以及设置缓存策略,没有任何改善。

作为参考,这是我的帖子请求的样子:

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:@"POST"];

NSString *contentType = [NSString stringWithFormat:@"text/xml"];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"]; 

NSMutableData *postBody = [NSMutableData data];
[postBody appendData:[xmlMessage dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:postBody];

//get response
NSHTTPURLResponse* urlResponse = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&httpError];

任何帮助都会得到热烈的掌声。

【问题讨论】:

  • 您是否使用辅助线程来执行此操作?
  • 另外,您是否大致了解您希望下载的总 MB 数?我想知道这与您提供的 190 MB 数字相比如何。
  • @Jim 不,不是辅助线程。当这些请求通过时,主线程上的进度条正在更新。就总大小而言,在我的模拟器中查看文档文件夹,大约 300 - 400 MB。

标签: objective-c ios nsurlconnection nsurlcache


【解决方案1】:

如果您真的想对同步请求执行此操作,那么您可以考虑显式地重新分配和释放每个请求中使用的对象。使用自动释放池意味着每个请求的剩余碎片都位于自动释放池中,直到池被耗尽。

如果您有一个 for 循环或其他一些循环来处理这些请求,您还可以在循环内创建一个更本地的自动释放池,然后在循环结束之前将其排空。如果您这样做,并且您想要保留超出该循环(和池)范围的数据,则应将其保留在循环中并在稍后的某个时间释放它。

在某些时候,根据您的经验水平,您应该考虑在辅助线程上执行此操作。您可以将每个 fetch 视为一个独立的操作,然后使用 NSOperation 和 NSOperationQueue 之类的东西来管理它。这样,您可以同时启动多个操作,而不会在等待每个响应时阻塞您的线程。

【讨论】:

  • 所以我们的 HttpRequest 对象被初始化为autorelease 在实际发出请求调用的循环之外。游泳池被释放了几层。我将 HTTPRequest 对象初始化移到 for 循环内,并专门为循环添加了 AutoReleasePool。到目前为止,CFData(存储)还没有超过 12 MB,它通常保持在 8 MB 左右。我的下载量是 45%。似乎是这样做的正确方法。至于 NSOperationQueue,它的简单程度如何?
  • 网络上有很多关于 NSOperation 和 NSOperationQueue 的内容,但我从来没有在一个地方找到我需要的一切。从谷歌搜索 Ray Wenderlich GCD 开始,看看他的例子。一旦您了解了与 iOS 环境中的线程和操作相关的几个因素,它就会看起来很简单。但是这里可以说的还不止这些。祝你好运。
  • 事实上,Ray 的示例与您正在做的非常接近。看看这个。 (由于某种原因,我无法将链接粘贴到我的 iPad 上。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-16
  • 2014-04-06
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
  • 2016-08-01
相关资源
最近更新 更多