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

时间:2012-01-06 15:46:34

标签: iphone objective-c ipad ios5 automatic-ref-counting

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

我只是想知道,手动不保留/释放的便利性(以及可能因此产生的更可靠的代码?)是否超过使用ARC的任何“成本”? 您对ARC有什么经历,您会推荐它吗?

所以:

  • ARC可以为项目带来多少好处?
  • ARC是否有类似垃圾收集的成本?
  • 您是否一直在使用ARC,如果是这样,到目前为止您是如何找到它的?

6 个答案:

答案 0 :(得分:147)

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

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

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

  • 与Core Foundation代码桥接有一些(非常)小的复杂性。在处理将id视为void*的任何事情时,会出现一些并发症。像id的C阵列这样的东西可以多考虑​​做一些正确的事情。对ObjC va_args的精细处理也会带来麻烦。涉及ObjC指针数学的大多数事情都比较棘手。在任何情况下你都不应该有这么多。

  • 您无法将id放入struct。这种情况非常罕见,但有时它会用于打包数据。

  • 如果您没有遵循正确的KVC命名,并且混合使用ARC和非ARC代码,则会出现内存问题。 ARC使用KVC命名来做出有关内存管理的决策。如果它是所有ARC代码,那么它无关紧要,因为它会在两侧都做同样的“错误”。但如果它是混合的ARC /非ARC,则存在不匹配。

  • 在ObjC异常抛出期间,ARC将泄漏内存。 ObjC异常应该在程序终止时非常接近。如果您正在捕获大量的ObjC异常,那么您正在错误地使用它们。这可以使用-fobjc-arc-exceptions来修复,但会产生下面讨论的处罚:

  • 在ObjC或C ++异常抛出ObjC ++代码期间,ARC不会泄漏内存,但这会以时间和空间性能为代价。这是为了最大限度地减少使用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。不幸的是,Xcode比实际应该做的要困难得多。您可能应该将非ARC代码移动到单独的xcodeproj中以简化此操作。

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


修改

我已经看到了一些注释:“使用ARC无法替代了解Cocoa内存管理规则。”这基本上是正确的,但重要的是要理解为什么以及为什么不这样做。首先,如果您的所有代码都使用ARC,并且您在整个地方违反了Three Magic Words,那么您仍然没有问题。令人震惊的说,但你去了。 ARC可能会保留一些您不想保留的东西,但它也会释放它们,因此它永远不会重要。如果我今天在Cocoa中教一个新课程,我可能花费不超过五分钟来实际的内存管理规则,我可能只会在讨论KVC命名时提及内存管理命名规则。有了ARC,我相信你可以在没有学习内存管理规则的情况下成为一个体面的初级程序员。

但你不可能成为一个体面的中级程序员。您需要了解规则才能与Core Foundation正确连接,并且每个中级程序员都需要在某些时候处理CF.您需要了解混合ARC / MRC代码的规则。当你开始使用void*指向id(你仍然需要正确执行KVO)时,你需要知道规则。阻止......好吧,阻止内存管理很奇怪。

所以我的观点是底层内存管理仍然很重要,但是我曾经花费大量时间来为新程序员说明和重述规则,而ARC正在成为一个更高级的主题。我宁愿让新的开发人员在对象图方面思考,而不是用objc_retain()的基础调用填充他们的头脑。

答案 1 :(得分:20)

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

  • ARC!=垃圾收集。没有运行时间惩罚,它是在编译时完成的。
  • ARC也!=只是自动发布所有内容,正如您在评论中所建议的那样。阅读docs
  • 一旦你意识到 做了多少人工参考管理,那真是太棒了
  • 使用它!
  • 一个缺点 - 保持旧的非弧形代码突然变得非常繁琐。

答案 2 :(得分:16)

  

ARC能为项目带来多少好处?

该好处是对常见内存管理错误的重要保护。由于未能保留或过早释放物体而导致未能释放物体和碰撞所导致的泄漏应该显着减少。您仍然需要了解引用计数的内存模型,以便您可以将引用分类为强或弱,避免保留周期等。

  

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

iOS中没有垃圾收集。 ARC类似于GC,因为您不必手动保留或释放对象。它不像GC那样没有垃圾收集器。保留/释放模型仍然适用,只是编译器在编译时为您的代码插入适当的内存管理调用。

  

您是否一直在使用ARC,如果是这样,到目前为止您是如何找到它的?

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

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

答案 3 :(得分:4)

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

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

那就是说,我个人是一名工匠,尚未进行过渡。我刚开始使用Git ......

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

答案 4 :(得分:2)

我在几个(不可否认的小项目)中使用它,我只有很好的经验,无论是性能还是可靠性。

一个小小的注意事项是你需要学习do:s而不是:如果你自己编写你的UI,那么弱引用不引起任何引用循环,设计师倾向于做好事如果您使用它设置GUI,它会自动完成。

答案 5 :(得分:2)

我遇到的唯一缺点是你使用的库中有很多CoreFoundation函数和数据。在MRC中,您无需担心使用CFStringRef而非NSString*。在ARC中,你必须指定两者如何交互(基本桥?释放CoreFoundation对象并将其移动到ARC?将Cocoa对象作为+1 CoreFoundation保留对象?)另外,在OS X上,它仅在64-上可用位代码(虽然我有一个可以解决这个问题的标题......)。