iphone如何在频繁加载图像时管理内存

时间:2011-10-20 05:28:45

标签: iphone ios memory

我正在编写我的应用程序,经常加载图像(但不是相同的图像)。就我测试而言,没有内存泄漏问题,但随着我加载不同的图像,应用程序的内存使用量也会增加。这意味着当应用程序达到内存上限时,应用程序最终会被操作系统杀死。我通过仪器进行了检查,发现NSConcreteData有很多内存。

memory allocation after the view is dismissed

//from different thread, and pass data to main thread
NSData *data = [[[NSData alloc] initWithContentsOfURL:url] autorelease];
//at main, data to uiimage
imgView.image = [[[UIImage alloc] initWithData:data] autorelease];

当视图被解除并且所有分配的内存都返回堆时,它看起来像是内存 我为NSData分配了保存在内存中的内容,因此与加载图像之前相比,应用程序的内存使用量增加了。我不确定这是否是正常行为。 或者在不同的线程之间传递分配的内存是不好的做法?

3 个答案:

答案 0 :(得分:2)

这可能对您的确切情况有所帮助,但通常会通过密切关注您的自动释放堆栈增长来减少这种情况。您应该能够通过在自动释放池块中包装那些繁重的创建者(来自url的数据,带有数据的图像)来减少问题。

@autoreleasepool { work with large NSObjects here }

或者,取决于您必须部署的系统:

NSAutoreleasePool * pool = [NSAutoreleasePool new];
work with large NSObjects here
[pool release];

如果您可以使用@autoreleasepool,请执行此操作。它稍微好一些,因为它直接与底层自动释放堆栈接口。如果您需要向后兼容性,请使用NSAutoreleasePool。在更高的层次上,它们确实服务于相同的目的,因为您应该能够在程序中交换它们的实现而不会引入新的问题。因此,它确实归结为您所定位的最小操作系统以及您在决定使用哪个时为项目指定的构建设置。

你应该在自动释放块中包装你的大量(或许多)分配的处理和创建,因为自动释放的对象会在“将来的某个时刻”发送释放消息。通过显式创建和销毁该自动释放池(并且通过较少使用自动释放),您可以更快地销毁许多这些对象。

至于为什么除了在您的程序中不使用自动释放之外,这可能是好的:客户端和系统库可能最终将您的大/多个图像/ NSData添加到自动释放池中。自动释放池就像(线程本地)堆栈 - 当您销毁本地池时,所有那些在池位于顶层时发出的自动释放消息将被实现,并且自动释放的对象将收到它们的释放消息。

  

或者在不同的线程之间传递已分配的内存是不好的做法?

请记住,您应该从主线程发送UIKit和AppKit对象。在Cocoa中,许多库可以指定它们的线程模型。 NSData遵循Foundation基础线程模型。这些对象不是显式线程安全的,但如果您在任何给定时间从不超过一个线程读取和/或写入它们是安全的(也就是说,只要您需要在MT上下文中使用它,就使用锁定,或者传递副本)。传递和共享数据/对象并不是一种坏习惯,有时(或逻辑解决方案)是必要的。稍微有些人说它“不坏”:许多人不了解多线程并且很好地共享资源(对许多人来说,这不是一项琐碎的技能)。

答案 1 :(得分:1)

尝试这样的事情。自动释放不如明确释放精确。

//on background thread data's retain count will now be 1
NSData *data = [[NSData alloc] initWithContentsOfURL:url];


//on main thread (I'm assuming .image is a retained property)
UIImage *newImage = [[UIImage alloc] initWithData:data];
imgView.image = newImage;
[data release];
[newImage release];

答案 2 :(得分:0)

尝试打开分配来计算内存, 当你每次想要发布的东西时, 首先使它为零,确保没有人使用此变量。 否则就会崩溃。

在发布之前使变量等于nil。