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

Sim*_*ton 112 iphone objective-c ipad ios5 automatic-ref-counting

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

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

所以:

  • ARC为项目带来了多少好处?
  • ARC是否像Java中的垃圾收集一样?
  • 您是否一直在使用ARC,如果是这样,到目前为止您是如何找到它的?

Rob*_*ier 147

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

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

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

  • 桥接Core Foundation代码有一些(非常)小的复杂性.有稍微在处理任何治疗的并发症较多idvoid*.像C阵列这样的东西id可以多花些时间思考一下.对ObjC的精细处理va_args也会带来麻烦.涉及ObjC指针数学的大多数事情都比较棘手.在任何情况下你都不应该有这么多.

  • 你不能放入id一个struct.这是相当罕见的,但有时它用于打包数据.

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

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

  • 在ObjC++代码中抛出ObjC或C++异常时,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,并且您在整个地方违反了三个魔术词,那么您仍然没有问题.令人震惊的说,但你去了.ARC可能会保留一些您不想保留的东西,但它也会释放它们,因此它永远不会重要.如果我今天在Cocoa中教一个新课程,我可能花费不超过五分钟来实际的内存管理规则,我可能只会在讨论KVC命名时提及内存管理命名规则.有了ARC,我相信你实际上可以成为一个不错的开始程序员而根本不学习内存管理规则.

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

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

  • 有一件事要非常小心(在非ARC中也是如此,但更多的是在ARC,因为它现在看不见)是保留周期.我的建议是1)如果你发现自己存储一个objc块作为一个实例变量,需要仔细查看它,看看它是否可以捕获对象,它甚至是间接的.2)实际上设计你的对象图,而不是让它发生.如果你想编写好的代码,你必须*知道拥有什么.3)使用快照:http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory -growth / (3认同)
  • 没有提到一个严重的缺点:交叉兼容性.对于我们勇敢和愚蠢的灵魂,面对被称为跨平台编程的荒地,ARC根本不是一个选择,至少在GNU再次扩展他们的ObjC运行时和编译器功能之前(他们说更多的是在路上). (2认同)
  • 除了需要支持iOS 3.x设备外,您可以使用ARC.顺便说一句,确保使用Xcode进行转换(编辑>重构>转换为Objective-C ARC).在此过程中,Xcode会进行大量验证,以确保您的代码能够正常工作并找出违反这些设计准则的任何代码. (2认同)

jrt*_*ton 20

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

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


Cal*_*leb 16

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

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

垃圾收集真的"花费"多少钱?

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

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

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

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