去ARC还是不去ARC?优缺点都有什么?[关闭]


113

由于我目前正在处理的项目中的大多数代码都是在iOS 5.0之前编写的,因此我尚未使用ARC。

我只是在想,不手动保留/释放(由此带来的结果可能是更可靠的代码)的便利是否超过了使用ARC的任何“成本”?您对ARC有什么经验,您会推荐吗?

所以:

  • ARC可为项目带来多少收益?
  • ARC是否具有Java垃圾回收这样的成本?
  • 您是否一直在使用ARC?如果是,到目前为止,您是如何找到它的?

ipad / ios上没有垃圾回收。您在谈论OS X吗?
dasblinkenlight 2012年

1
抱歉,我过时使用了Java术语。我的意思是,使用ARC,对象可以在内存中保留的时间比必要的时间长,然后在一段时间后作为一组在自动释放池中释放。正是它们被保留并随后与其他对象一起释放的这种效果,类似于我所指的Java的垃圾回收。
西蒙·威辛顿

3
@TenementFunster,对于相同的代码(减去对release的调用),ARC将对象保留的时间不超过非ARC代码的时间。实际上,它通常会比您更快地发布它。少数情况有些慢,但是它们加快了通用模式的速度,以至于使性能影响相形见war。对于许多常见模式(例如,保留通过自动发布返回的对象),您实际上无法像ARC自动完成一样快地手动编写它。
Rob Napier 2012年

1
关于垃圾收集,请参见我对类似问题的回答:Objective-C自动引用计数和垃圾收集之间有何区别?
布拉德·拉尔森

Answers:


147

没有缺点。用它。今天就做。它比您的旧代码更快。它比旧代码更安全。它比您的旧代码容易。这不是垃圾收集。它没有GC运行时开销。编译器将在您应该拥有的所有位置中插入并释放。但是它比您更智能,并且可以优化不需要的内容(就像它可以展开循环,消除临时变量,内联函数等)一样。

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

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

  • 桥接到Core Foundation代码有一些(非常)小的麻烦。有稍微在处理任何更多的并发症治疗的id作为void*。像C数组这样的事情id可能需要更多的思考才能正确完成。花哨的处理ObjC va_args也会引起麻烦。在ObjC指针上涉及数学的大多数事情都比较棘手。在任何情况下,您都不应拥有太多。

  • 你不能把一个idstruct。这种情况很少见,但有时用于打包数据。

  • 如果未遵循正确的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()。进行底层调用。


3
保留周期是要特别注意的一件事(在非ARC中也是如此,但在ARC中也是如此,因为它现在已经不可见了)。我的建议是1)如果您发现自己将objc块存储为实例变量,请仔细研究一下它是否可以捕获它的ivar对象,甚至是间接的对象。2)实际上设计您的对象图,而不仅仅是让它发生。你必须知道,如果你想编写好的代码什么什么的拥有。3)使用heapshots:friday.com/bbum/2010/10/17/...
Catfish_Man

1
@Catfish_Man所有优点。保持循环一直是一个问题。苹果公司的新建议与您在#2中所说的完全一样。我们需要考虑对象图,而不是保留和释放。#1是区块的严重问题,我发现区块有多种原因之一,应谨慎对待。
罗布·纳皮尔

2
没有提到一个严重的缺点:交叉兼容性。对于那些面对荒废而又被称为跨平台编程的勇敢而愚蠢的人来说,ARC绝对不是一个选择,至少直到GNU再次扩展其ObjC运行时和编译器功能(他们说还有更多)时,ARC才成为可能。
Rabbit

2
您可以使用ARC,但需要支持iOS 3.x设备。顺便说一句,请确保使用Xcode进行过渡(“编辑”>“重构”>“转换为Objective-C ARC”)。在此过程中,Xcode将进行大量验证,以确保您的代码可以正常工作并找出违反那些设计准则的任何代码。
张扬

1
优秀..用点明智的答案。那是我的一百分 一个世纪的伙伴;)
阿杰·夏尔玛

20

比我的更好,更多的技术答案会出现,但是这里是:

  • ARC!=垃圾收集。没有运行时间损失,它在编译时完成。
  • ARC也!=就像您在评论中建议的那样,只是自动释放所有内容。阅读文档
  • 一旦意识到自己正在执行多少手动参考管理,那就太好了
  • 用它!
  • 一个缺点-维护旧的非弧形代码突然变得非常乏味。

是的,这就是到目前为止我还没有使用过它的原因-我不确定我是否愿意经历我们大量的现有代码来对其进行转换……不过,我肯定会在下一个项目中进行尝试。感谢您的回答:)
Simon Withington 2012年

不是维护旧代码变得更加困难,而是您的期望已经改变。因此,怪罪ARC会使生活更轻松是不公平的。使用Xcode可以轻松地将旧代码转换为ARC,但如果仍然需要支持旧版iOS,则显然无法使用它。
Caleb 2012年

1
@Caleb我并没有责怪ARC,这只是到目前为止我唯一看到的缺点-它破坏了我在单个项目中的工作。
jrturton 2012年

是的 我没有将其列为问题,但是当您必须在代码库之间进行切换时,存在一个摆脱内存管理实践的小问题。我的一些项目在10.4上运行,所以我仍然做很多Objective-C 1.0工作(所以没有@synthesize,更不用说ARC了)。但是您已经习惯了很好地切换模式。
罗布·纳皮尔

@jrturton我应该更清楚地指出,我写这篇文章是为了OP和未来读者的利益,他们可能不理解ARC的功能。我确切地知道您的意思,只是不想让任何人得出这样的错误结论:混合ARC和非ARC代码会造成问题。
卡勒布(Caleb)2012年

16

ARC可为项目带来多少收益?

好处是可以有效防止常见内存管理错误。因未能释放对象而导致的泄漏和因无法保留或过早释放对象而导致的崩溃应大大减少。您仍然需要了解引用计数的内存模型,以便可以将引用分类为强引用或弱引用,避免保留周期,等等。

垃圾回收真正地要多少钱?

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

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

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

ARC的唯一问题是,iOS的较早版本不支持ARC,因此在决定采用ARC之前,必须将其考虑在内。


1
我在说更好的答案!
jrturton 2012年

1
是的,很好的答案。因此,除了必须学会相信它起作用之外,ARC真的没有缺点吗?在那种情况下似乎太真实了吗?
西蒙·威辛顿

4

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

总结一下:ARC不是免费的通行证,它可以使内存无关紧要。它是一种工具,可帮助人们避免重复的任务,这些任务会造成压力并易于出错,因此最好委派给计算机(在这种情况下为编译器)。

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

更新:因此,我迁移了我的整个游戏,包括gl库,到目前为止没有任何问题(Xcode 4.2中的迁移助手除外)。如果您要开始一个新项目,请继续。


2

我已经在几个(非常小)的项目中使用了它,并且我在性能和可靠性方面都只有很好的经验。

一个小小的注意事项是,如果您自己编写UI,则需要学习弱引用的do:s和not:s不会引起任何引用循环,设计人员往往会做得很好如果您使用它来设置您的GUI,它会自动运行。


2

我遇到的唯一缺点是,如果您使用包含许多CoreFoundation函数和数据的库。在MRC中,您无需担心使用CFStringRef而不是NSString*。在ARC中,您必须指定两者的交互方式(基本桥?释放CoreFoundation对象并将其移至ARC?将可可对象作为+1 CoreFoundation保留对象?)而且,在OS X上,它仅在64-位代码(尽管我确实有解决该问题的标头…)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.