42

在 iOS 项目中使用新的自动引用计数 (ARC) 内存管理样式有哪些优点和缺点?

使用 iOS 5.0 SDK 开发时可以选择不使用 ARC 吗?

您是否为新项目推荐 ARC 或手动引用计数 (MRC)?

使用 ARC 的应用程序能否在比 iOS 5.0 更旧的操作系统版本上运行?

4

4 回答 4

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 是二进制兼容的,真正发生的事情是编译器会根据当前翻译可见的声明自动为您引入适当的引用计数操作(请参阅我的回答,了解为什么翻译可见性很重要) . 因此,您还可以为项目中的某些源启用和禁用它,并为其他源启用它。

然而,混合模式(一些 MRC 和一些 ARC 源)相当复杂,而且很微妙,尤其是编译器可能会复制的 wrt 实现(例如,内联函数的主体可能不正确)。这种混合模式问题将很难隔离。在这方面,ObjC++ 程序和源代码将特别困难。此外,行为可能会根据您的优化设置而有所不同(例如);在调试版本中完美运行的程序可能会在发布时引入泄漏或僵尸。

您是否为新项目推荐 ARC 或手动引用计数 (MRC)?

就个人而言,我会坚持使用 MRC 一段时间。即使 ARC 已经在现实世界的使用中进行了测试,在复杂的场景中也可能会出现一些问题,您将希望避免成为第一个知道和调试的人。OS X 的垃圾收集是您可能想要等待的一个例子。举个例子,当对象被销毁时,开关可能会改变——您的对象可能会更快地被销毁并且永远不会被放置在自动释放池中。它还可以更改 ivars 的发布顺序,这可能会产生一些副作用。

我也有一个庞大的代码库,我不想为此浪费一周的时间来测试这个特性。最后,向后兼容性对我来说仍然很重要。

使用 ARC 的应用程序能否在比 iOS 5.0 更旧的操作系统版本上运行?

如果您使用 MRC 进行开发,它将向后兼容。如果你用 ARC 开发,它不一定兼容。事实上,如果没有一点额外的工作,它甚至可能无法编译。运行时的要求在一些早期版本中可用。 另请参阅此问题。如果您需要向后兼容,ARC 将不是某些操作系统版本的选项。

最后,如果您要将选择限制为 GC 或 ARC,我会推荐 ARC。

于 2011-10-25T11:52:20.850 回答
1

你关闭/打开它的CLANG_ENABLE_OBJC_ARC = NO 好处是你必须编写更少的代码并且内存管理更容易。缺点是您必须从头开始学习有关内存管理的所有知识:) 我更喜欢将其关闭。

于 2011-10-25T11:49:32.473 回答
0

您可以通过“Edit->Refactor->Convert to Objective C Arc”打开 ARC,这将完全重构您的代码(摆脱所有内存管理调用等)。没有逆操作,因此如果您有第二个想法,请确保您已将内容置于源代码控制之下。这个帖子向您展示如何为特定文件禁用它。我认为没有太多理由不转向它,除了看到所有这些用于良好内存管理的努力付诸东流,我们将不得不停止跳到天花板上,这很痛苦。每次我们看到 init, new, copy 没有相应的发布/自动发布(这需要一些时间来适应)。也许有人会说,在某些情况下,手动内存管理会导致性能/内存占用的改进非常显着,如果是这样,我也会感兴趣。

于 2011-10-25T11:49:40.583 回答
0

我正在使用 Lion 和 xcode 4.3。我有同样的问题。

为了解决这个问题,我将“Build Settings->Objective-C Automatic Reference Co”设置为“No”。

为了看到它被设置为“是”,我还必须在“构建设置”工具栏下方的工具栏上启用“所有”和“级别”选项。

启用这些选项后,我可以看到我的项目将该选项设置为“是”。我花了一段时间才弄清楚,因为默认设置是“否”,这是在我启用“级别”选项之前显示的内容。

于 2012-02-19T22:58:37.063 回答