4

最近,当我查看iPhone内存管理时,我试图比较同一对象上的便捷方法和init方法。例如,我有UIImageView的地方显示一个下载NSData的:便捷方法vs初始化方法的内存使用情况

便捷方法:

imageView.image = [UIImage imageWithData:[downloads dataAtIndex:0]]; 

init方法:

UIImage *aImage = [[UIImage alloc] initWithData:[downloads dataAtIndex:0]]; 
imageView.image = aImage; 
[aImage release]; 

当我尝试去来回的意见,以增加内存使用率和命中“模拟内存警告”,应用程序的内存使用率从20MB到18MB,使用方便的方法,init方法立即从20MB变为13MB。

我也等待并与应用程序交互,以便在便捷方法的autorelease上发布时间。但它并没有太大下降。

除了autorelease vs版本之外,还有什么其他贡献了差异?

回答

1

可能导致此问题的唯一区别是imageWithData:不使用系统映像缓存,而initWithData:执行。因此,也许初始化程序制作的图像在收到内存警告时可以释放它的图像数据,因为它可以返回到系统缓存,而由便捷方法创建的图像不能。

1

使用便捷方法创建的对象是自动发布的,因为我相信您知道。但是,如果在创建映像的RunLoop中没有AutoReleasePool,则该对象将被添加到一个不存在的池中,并且从未正确清理。如果你正在一个线程中运行,并且忘记为该线程创建一个AutoReleasePool,则可能是这种情况。

要验证是否属于这种情况,您可以运行仪器(泄漏)并查看它报告的内容。

+1

如果不存在自动释放池,则当您尝试创建自动释放对象fyi时,应该会将警告打印到控制台。 – 2008-11-14 13:57:59

+0

它应该在主线程,因此它可能不相关... – leonho 2008-11-14 15:44:30

4

由便捷方法创建的自动释放对象将不会被释放,直到包含的autorelease池被耗尽。如果您要大量使用它们,则建议将内存密集型操作包装在NSAutoreleasePool块中。

1

我注意到的一点是,对于自动释放对象,在内存压力下,如果没有及时释放池,系统GC会出现明显的性能下降。

另外,使用init/release方法可以让循环中的内存消耗保持不变,而使用autorelease池会产生尖峰。在一些内存质疑异常的情况下,自动释放池中对象的快速增加可能会导致应用程序在系统采取措施清理诸如正在打开的电子邮件,移动Safari标签和iTunes等东西运行之前启动。底线,我倾向于更多地使用init,因为它使我的应用程序的内存消耗更加一致,并且我看到随机引导的问题更少。内存消耗的逐渐增加让守护进程清理系统而不会中止我的应用程序。最后,作为有点的一边,如果您使用的是@属性关键字在你的类,你必须要小心之类的东东:

myProperty = [NSMutableArray arrayWithCapacity:10]; 

因为会发生什么是当你的main.m类池收集该项目将会消失,由于在释放的对象上调用方法而导致崩溃。如果您使用@property(nonatomic,retain)设置它,您将需要使用:

self.myProperty = [NSMutableArray arrayWithCapacity:10]; 

确保它挂起。然而,只要使用alloc init就可以避免所有这些。只要看你的引用计数,以确保你没有引起内存泄漏的双引用。