避免自动释放的物体,良好做法或过度杀伤?

时间:2011-02-16 17:44:21

标签: iphone objective-c cocoa-touch memory-management

我对以下内容感到好奇,当我编写代码时,我总是尝试通过坚持使用非自动释放的对象来管理内存。我知道这意味着物体不会在水池中闲逛,但我只是好奇,如果一般这样做是好的做法还是仅仅是矫枉过正?

// User Managed Memory
NSSet *buttonSizes = [[NSSet alloc] initWithObjects:@"Go", @"Going", @"Gone", nil];
[barItemLeft setPossibleTitles:buttonSizes];
[barItemRight setPossibleTitles:buttonSizes];
[buttonSizes release];

// Autoreleased Memory
NSSet *buttonSizes = [NSSet setWithObjects:@"Go", @"Going", @"Gone", nil];
[barItemLeft setPossibleTitles:buttonSizes];
[barItemRight setPossibleTitles:buttonSizes];

6 个答案:

答案 0 :(得分:8)

总矫枉过正。如果您仔细阅读相关文档,则不会说您应该避免自动释放对象。它表示当你处于紧密的,对象丰富的循环中时,应该避免使用自动释放池。在这些情况下,您应该明确管理您的内存(使用retainrelease)以确保以摊销方式创建和销毁对象。

iPhone是一个受内存限制的环境的论点是正确的,但完整的红色鲱鱼。 Objective-C,使用Foundation和Cocoa框架(虽然当时没有调用它们),在NeXTcube上运行就好了,它有16MB的RAM(可扩展到64)。即使是iPhone 3,此时已经非常EOL,也有128MB。

修改

由于iPhone应用程序是基于runloop的应用程序,因此每次旋转时都会创建并销毁新的自动释放池。这在文档中有明确定义。因此,您必须创建自己的自动释放池的唯一原因是:

  • 产生后台线程,必须创建自己的池(因为新线程默认情况下没有基本ARPool)
  • 执行一些操作,生成大量自动释放的对象。在这种情况下,创建和排空池将有助于确保临时对象的有限生命周期。

但是,在第二种情况下,建议您尽可能明确地管理内存。这样,当你的操作试图排空一个有几千个物体的游泳池时,你的操作就不会嘎然而止。如果您手动管理内存,则可以逐步释放这些对象,而不是将它们保存为单个一次性版本。您可以通过嵌套ARPools帮助分摊一次性发布,这将有所帮助。

但是,在一天结束时,只做自然感觉,然后(并且然后)优化它,如果你有具体的证据表明你需要这样做。

编辑#2

好的,事实证明 recommendation to avoid using autorelease但是该建议位于“iOS应用程序编程指南”的“性能和响应性调优”区域的“分配内存明确”部分。换句话说,如果您正在测量性能问题,请避免使用 。但严重的是:autorelease已经存在了大约20年,并且在计算机上做得很好,比今天的iDevices更慢,更受限制。

答案 1 :(得分:3)

除非您发现性能问题(或内存问题),否则我不担心使用自动释放池。此外,理论上的自动释放比非自动释放更有效。使用自动释放的真正危险的地方是大循环(例如,导入大型数据集时)。在这些情况下,您可能会耗尽有限的iPhone内存。

我建议您在完成应用程序后专注于删除自动释放用法,并使用内置仪器识别内存管理问题。

答案 2 :(得分:2)

如果可能,我喜欢使用自动释放方法。它消除了我忘记释放它们或有人进来并改变代码流以便绕过显式释放的机会。我投票说自我管理版本是过度的。

答案 3 :(得分:1)

有一个平衡点。这在很大程度上取决于具体情况。在这种特殊情况下,假设barItem*变量是长寿命的ivars,避免自动释放非常接近100%毫无意义,因为无论你现在还是现在两秒钟发布它,该集合都将保持不变。 / p>

事实上,在大多数情况下,现在或者在runloop的下一次迭代中释放对象几乎没有什么区别,因为runloop的速度非常快,以至于它实际上能够创建平滑动画 。 iPhone是一个特别缺乏记忆的平台,所以不要把事情留得太长时间。但与此同时,要切合实际:一个自动释放的NSNumber在一个每隔几秒钟调用一次的方法中甚至不会削弱你的应用程序的配置文件。即使是10万字符的NSStrings也只能使用iPhone 3GS上大约0.065%的系统RAM。只有当你在很短的时间内积累了大量的东西时,这才会变得非常重要。所以,如果没有问题,请不要出汗。

答案 4 :(得分:1)

这取决于是否有自动释放池。例如,如果您在AudioUnit的渲染回调中使用objective-c对象(从没有自动释放池的单独线程调用),则自动释放的对象将泄漏。在这种情况下,手动释放它们或将它们包装在自动释放池中非常重要。

总的来说,我认为这取决于你和你的编码风格

答案 5 :(得分:1)

我认为只有一个合理的答案:通常自动释放不是性能问题。最好记住,它可能在紧密循环中存在问题,但除非像仪器这样的性能表显示出你必须摆脱的内存峰值,否则如果你愿意,我会使用它。

过早优化是花时间无所事事的好方法。也许最后你知道你的解决方案很优雅,但可能更简单的解决方案也可以表现得很好。