最近,当我查看iPhone内存管理时,我试图在同一个对象上比较方便方法和init方法。例如,我有UIImageView,它显示下载的NSData:
便利方法:
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 vs release之外,还有什么促成了差异?
答案 0 :(得分:4)
在排除包含自动释放池之前,不会释放由方便方法创建的自动释放对象。如果你要大量使用它们,建议在NSAutoreleasePool
块内包装内存密集型操作。
答案 1 :(得分:1)
可能导致这种情况的唯一区别是imageWithData:不使用系统映像缓存,而initWithData:则使用系统映像缓存。因此,使用初始化程序创建的图像可能会在收到内存警告时释放它的图像数据,因为它可以返回到系统缓存,而由方便方法创建的图像则不能。
答案 2 :(得分:1)
使用便捷方法创建的对象是自动释放的,我相信你知道。但是,如果在创建映像的RunLoop中没有AutoReleasePool,则该对象将添加到不存在的池中,并且永远不会正确清理。如果您在一个线程中运行,并且忘记为该线程创建一个AutoReleasePool,则可能就是这种情况。
要验证是否是这种情况,您可以运行Instruments(Leaks)并查看它报告的内容。
答案 3 :(得分:1)
我注意到的一点是,对于自动释放的对象,在内存压力下,如果您没有及时释放池,系统GC会出现明显的性能损失。
此外,使用init / release方法可以使循环中的内存消耗保持不变,而使用自动释放池会产生峰值。在一些内存挑战的版本中,自动释放池中对象的快速增加可能会导致应用程序在系统采取措施清理电子邮件打开,移动safari选项卡和iTunes内容等操作之前启动。
总而言之,我更倾向于使用init,因为它使我的应用程序的内存消耗更加一致,并且我看到随机启动的问题更少。内存消耗的逐渐增加使守护进程可以清理系统而不会杀死我的应用程序。最后,如果你在课堂上使用@property关键字,你必须要小心:
myProperty = [NSMutableArray arrayWithCapacity:10];
因为会发生什么事情,当你的main.m类中的池被收集时,该项将被消失,由于在已发布的对象上调用方法而导致崩溃。如果您使用@property(非原子,保留)进行设置,则需要使用:
self.myProperty = [NSMutableArray arrayWithCapacity:10];
确保它挂起。但是,您可以通过使用alloc init来避免所有这些。只需观察您的引用计数,确保没有引用内存泄漏的双重引用。