在iOS项目中使用新的自动引用计数(ARC)内存管理方式有哪些优缺点?
使用iOS 5.0 SDK进行开发时,您可以选择不使用ARC吗?
您是否建议为新项目使用ARC或手动引用计数(MRC)?
使用ARC的应用程序是否能够在比iOS 5.0更旧的操作系统版本上运行?
答案 0 :(得分:60)
在iOS项目中使用新的自动引用计数(ARC)内存管理方式有哪些优缺点?
ARC程序的执行与编写良好的MRC几乎相同。也就是说,行为差异通常是不可检测的,因为操作顺序和性能都非常接近。
如果您已经知道如何使用手动引用计数(MRC)实现OS X或iOS应用程序,ARC并不真正添加功能 - 它只允许您从源中删除引用计数操作。
如果您不想学习MRC,那么您可能需要先尝试ARC。很多人都在努力或试图忽略MRC的常见做法(例如:我向静态分析器介绍了一些objc开发人员)。如果你想避免这些问题,ARC将允许你推迟你的理解;如果不了解引用计数和对象生命周期和关系,无论是MRC,ARC还是GC,都不能编写非平凡的objc程序。 ARC和GC只是从您的源中删除实现,并在大多数情况下做正确的事情 。使用ARC和GC,您仍需要提供一些指导。
我没有对此进行测量,但值得一提的是编译 ARC源会占用更多时间和资源。
如果您正在开发的程序使用引用计数相当松散(例如,典型的自动释放量),切换到ARC 可能真正改善程序的执行时间和峰值内存使用量。
使用iOS 5.0 SDK进行开发时,您可以选择不使用ARC吗?
是的,使用CLANG_ENABLE_OBJC_ARC。 ARC是二进制兼容的,所有真正发生的事情是编译器尽力为您自动引入适当的引用计数操作,基于当前转换(see my answer here as to why translation visibility is important)可见的声明。因此,您还可以为项目中的某些源启用和禁用它,并为其他源启用它。
然而,混合模式(一些MRC和一些ARC源)非常复杂,并且巧妙地,特别是可能被编译器复制的实现(例如,内联函数的主体可能是不正确的)。这种混合模式问题很难分离。在这方面,ObjC ++程序和来源将特别难以实现。此外,行为可能会根据您的优化设置而有所不同(作为一个示例);在调试版本中完美运行的程序可能会在发布时引入泄漏或僵尸。您是否建议为新项目使用ARC或手动引用计数(MRC)?
就个人而言,我会坚持使用MRC一段时间。即使ARC已经在实际使用中进行了测试,但很可能会出现一些问题,这些问题会出现在复杂的场景中,您可能希望避免成为第一个知道和调试的问题。 OS X的垃圾收集是您可能想要等待的原因的一个示例。作为一个例子,交换机可以在对象被销毁时改变 - 您的对象可能会被更快地销毁,并且永远不会被放置在自动释放池中。它也可能改变释放ivars的顺序,这可能会产生一些副作用。
我还有一个庞大的代码库,我不想在这个时候丢失一周的时间来测试这个功能。最后,向后兼容对我来说仍然很重要。
使用ARC的应用程序是否能够在比iOS 5.0更旧的操作系统版本上运行?
如果您使用MRC进行开发,它将向后兼容。如果使用ARC开发,则不一定兼容。事实上,如果没有一点额外的工作,它甚至可能无法编译。某些早期版本中提供了运行时的要求。 See also this question。如果您需要向后兼容性,ARC将不适用于某些操作系统版本。
最后,如果您要将选择限制在GC或ARC,我建议使用ARC。
答案 1 :(得分:1)
您使用CLANG_ENABLE_OBJC_ARC = NO
关闭/打开它
优点是你必须编写更少的代码并且内存管理更容易。缺点是你必须抓住你所学到的关于内存管理的一切:)我更喜欢把它关掉。
答案 2 :(得分:0)
您可以通过“Edit-> Refactor->转换为Objective C Arc”打开ARC,这将完全重构您的代码(摆脱所有内存管理调用等)。没有逆操作,所以如果你有第二个想法,请确保你有源于控制的东西。 This post向您展示了如何为特定文件禁用它。我不认为有太多的争论要做,因为除了看到所有这些努力投入到良好的记忆管理中而伤害我们将不得不停止跳到天花板的事实之外每次我们看到init,new,copy而没有相应的发布/自动释放(这需要一些时间来习惯)。或许可以说,在某些情况下,手动内存管理会带来非常明显的性能/内存占用改进,如果是这样,我也会感兴趣。
答案 3 :(得分:0)
我正在使用Lion和xcode 4.3。 我遇到了同样的问题。
为了解决这个问题,我转向了#34; Build Settings-> Objective-C Automatic Reference Co"到"否"。
为了看到它被设置为"是"我还必须启用" All"和"级别"工具栏上的选项位于"构建设置"工具栏。
启用这些选项后,我可以看到我的项目将该选项设置为"是"。我花了一段时间来确定默认设置是" No",这是显示的,直到我启用" Levels"选项。