4

最近在研究 iPhone 内存管理时,我尝试比较同一个对象上的便捷方法和 init 方法。例如,我有 UIImageView,它显示下载的 NSData:

便捷方法:

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

初始化方法:

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

当我尝试在视图上来回切换以增加内存使用量并点击“模拟内存警告”时,应用程序的内存使用量使用便捷方法从 20MB 变为 18MB,而 init 方法立即从 20MB 变为 13MB。

我还等待并与应用程序交互,以便在便捷方法的自动释放上释放时间。但并没有下降太多。

除了自动发布与发布之外,还有什么造成了差异?

4

4 回答 4

4

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

于 2008-11-14T17:40:21.213 回答
1

Something that I have noticed is that with autoreleased objects, under memory pressure, there is a system GC that occurs with a noticeable performance hit if you don't release your pools in a timely fashion.

Also, using the init / release method allows your memory consumption in loops to remain flat, while using a autorelease pool creates spikes. In some memory challenged contitions, the rapid increase of objects in the autorelease pool may cause your application to get booted before the system takes steps to clean up stuff like emails being open, mobile safari tabs, and iTunes stuff running.

Bottom line, I tend to use init more because it makes my application's memory consumption more consistent and I see fewer problems with getting booted randomly. The gradual increase in memory consumption lets the daemons clean up the system without killing my app. Finally, as somewhat of an aside, if you are using the @property keyword in your classes, you have to be careful with stuff like:

myProperty = [NSMutableArray arrayWithCapacity:10];

Because what will happen is when the pool in your main.m class gets collected that item will be gone, causing a crash due to calling a method on a released object. If you are setting it with @property (nonatomic, retain) you will want to use:

self.myProperty = [NSMutableArray arrayWithCapacity:10];

to make sure it hangs around. You can avoid all of that by just going with alloc init however. Just watch your reference counts to make sure you don't have double references causing memory leaks.

于 2009-05-13T21:53:53.933 回答
1

可能导致这种情况的唯一区别是 imageWithData: 不使用系统图像缓存,而 initWithData: 使用。因此,也许使用初始化程序创建的图像可以在收到内存警告时释放其图像数据,因为它可以返回系统缓存,而通过便捷方法创建的图像则不能。

于 2008-11-14T09:42:29.803 回答
1

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

要验证是否是这种情况,您可以运行 Instruments (Leaks) 并查看它报告的内容。

于 2008-11-14T13:20:10.677 回答