要ARC还是不要ARC? 优缺点都有什么?

我还没有使用ARC,因为目前正在处理的项目中的大部分代码都是在iOS 5.0之前编写的。

我只是想知道,不手动保留/释放的方便性(大概是可靠性更高的代码)会超过使用ARC的“成本”吗? 你有什么经验的ARC,你会推荐它?

所以:

  • ARC能为项目带来多less好处?
  • ARC在Java中有像垃圾收集一样的成本吗?
  • 你有没有使用ARC,如果是的话,你到目前为止如何find它?

没有缺点。 用它。 今天做。 它比你的旧代码更快。 这比旧的代码更安全。 这比旧的代码更容易。 这不是垃圾收集。 它没有GC运行时间的开销。 编译器插入保留和释放所有你应该有的地方。 但是它比你更聪明,可以优化那些实际上不需要的(就像它可以展开循环,消除临时variables,内联函数等)

好的,现在我会告诉你一些小缺点:

  • 如果您是一位长期的ObjC开发人员,当您看到ARC代码时,您将抽搐约一周。 你很快就会克服这个。

  • 在桥接Core Foundation代码时有一些(非常)小的复杂性。 在处理任何将id作为void*情况下,会有更多的复杂性。 像C的数组的id可以采取更多的想法做一个正确的。 处理ObjC va_args也会造成麻烦。 涉及ObjC指针math的大部分事情是比较棘手的。 在任何情况下,你都不应该有太多这样的事情。

  • 你不能在一个struct放置一个id 。 这是相当罕见的,但有时它被用来打包数据。

  • 如果您没有按照正确的KVC命名,并且混合使用ARC和非ARC代码,则会出现内存问题。 ARC使用KVC命名来做出关于内存pipe理的决定。 如果是全部的ARC代码,那么它就不会有问题,因为它会在两边做同样的“错误”。 但是,如果ARC /非ARC混合,则会出现不匹配。

  • ARC将在ObjCexception抛出期间泄漏内存。 ObjC例外应该是非常接近你的程序终止。 如果你正在捕获大量的ObjCexception,那么你就错误地使用了它们。 这可以通过使用-fobjc-arc-exceptions ,但是会导致下面讨论的处罚:

  • 在ObjC或C ++exception抛出ObjC ++代码期间,ARC不会泄漏内存,但这是以时间和空间性能为代价的。 这是一个长长的列表中的另一个原因,以尽量减less您使用ObjC ++。

  • ARC在iPhoneOS 3或Mac OS X 10.5或更早版本上根本不起作用。 (这阻碍了我在许多项目中使用ARC。)

  • __weak指针在iOS 4或Mac OS X 10.6上无法正常工作,这是一个耻辱,但相当容易解决。 __weak指针非常棒,但它们不是ARC的头号卖点。

对于95%以上的代码,ARC非常出色,没有任何理由可以避免(假设您可以处理操作系统版本限制)。 对于非ARC代码,可以-fno-objc-arc文件地传递-fno-objc-arc 。 不幸的是,Xcode比实际上要做得更难。 您应该将非ARC代码移入单独的xcodeproj以简化此操作。

总之,尽快切换到ARC,永远不要回头。


编辑

我已经看到了一些评论:“使用ARC不能替代知道Cocoa内存pipe理规则”。 这大部分是正确的,但是理解为什么和为什么不重要。 首先,如果你所有的代码都使用ARC,而且你违反了这个地方的三个魔法字 ,你仍然没有问题。 令人震惊地说,但是你去了。 ARC可能会保留一些你不想保留的东西,但是它也会释放它们,所以它永远不会有问题。 如果我今天在Cocoa上教授一门新课,我可能会花费不到五分钟的时间来处理实际的内存pipe理规则,在讨论KVC命名时,我可能只会提到内存pipe理命名规则。 用ARC,我相信你实际上可以成为一个体面的开端程序员,根本不学习内存pipe理规则。

但你不能成为一个体面的中级程序员。 您需要了解这些规则才能正确搭buildCore Foundation,每个中级程序员都需要在某个时候处理CF。 你需要知道混合ARC / MRC代码的规则。 当你开始用void*指向id指针(你需要继续正确的执行KVO)的时候,你需要知道规则。 而块…好吧,阻止内存pipe理是奇怪的。

所以我的观点是,底层的内存pipe理仍然是重要的,但是我曾经花费大量时间来陈述和重申新程序员的规则,而使用ARC就成为了一个更高级的话题。 我宁愿让新开发人员根据对象图来思考,而不是用objc_retain()的底层调用来填补他们的头脑。

比我的更好,更技术性的答案会来,但这里有:

  • ARC!=垃圾收集。 没有运行时间的惩罚,它是在编译时完成的。
  • ARC也!=只是自动释放一切,正如你在你的评论中所build议的。 阅读文档
  • 一旦你意识到你正在做多less手动引用pipe理,这真是太棒了
  • 用它!
  • 一个缺点 – 保留旧的非弧代码突然变得非常繁琐。

ARC能为项目带来多大的收益?

这个好处是对常见的内存pipe理错误有很大程度的保护。 由于未能保留或过早释放物体而未能释放物体而引起的泄漏应该大大减less。 您仍然需要了解引用计数的内存模型,以便您可以将引用分类为强或弱,避免保留周期等等。

垃圾收集真的“花费”多less钱?

iOS中没有垃圾回收。 ARC类似于GC,因为您不必手动保留或释放对象。 这不像GC,没有垃圾收集器。 保留/释放模型仍然适用,只是在编译时,编译器会为您插入相应的内存pipe理调用。

你有没有使用ARC,如果是的话,你到目前为止如何find它?

如果你习惯于引用计数,这有点令人不安,但这只是一个习惯它,并学会相信编译器真的会做正确的事情的问题。 它感觉像Objective-C 2.0所带来的属性变化的继续,这是简化内存pipe理的又一大步。 没有手动内存pipe理调用,你的代码变得更短,更容易阅读。

ARC唯一的问题是它在旧版本的iOS中不受支持,因此在决定采用它之前,需要考虑到这一点。

我认为ARC是一个好主意。 与GC相比,你可以吃你的蛋糕,也可以吃。 我倾向于认为,MRC为memory management强加一个无价的“纪律”,每个人都可以从中受益。 但是我也同意,真正要注意的问题是对象所有权和对象图(正如很多人指出的那样),而不是低级别的引用计数本身。

最后得出结论:ARC并不是一个无意识的记忆, 它是一个帮助人类避免重复性任务的工具,它会导致压力并容易出错,因此更好地委托给一台机器(在这种情况下是编译器)。

这就是说,我个人是一个工匠,还没有过渡。 我刚开始使用Git …

更新:所以我迁移了我的整个游戏,包括gl库,到目前为止没有问题(除了在Xcode 4.2中的移植助手)。 如果你正在开始一个新的项目,就去做吧。

我已经在一些(不可多得的)项目中使用过它,而且我只有很好的经验,兼顾性能和可靠性。

需要注意的一点是,如果你自己编写你的用户界面,你需要学习do和s:不要引用弱引用,否则不会引起任何引用循环,devise者往往会做得很好自动如果你使用它来设置你的GUI。

我遇到的唯一不足就是如果你使用一个具有大量CoreFoundation函数和数据的库。 在MRC中,您不必担心使用CFStringRef而不是NSString* 。 在ARC中,你必须指定两者如何相互作用(基础桥释放CoreFoundation对象并将其移动到ARC?将Cocoa对象设置为+1 CoreFoundation保留对象?)另外,在OS X上,位代码(虽然我有一个头,围绕…)。