如果我们覆盖保留/释放方法,我们是否会丢失ARC的objc_retain()/ objc_release()优化?

时间:2014-12-12 10:07:03

标签: ios objective-c memory-management automatic-ref-counting clang

已编辑:有些人认为来自 AsyncDisplayKit ASDealloc2MainObject 并未真正覆盖保留/释放。我修改了 ASDealloc2MainObject line 405-428 of _AS-objc-internal.h)后面的源代码,在重写的发布方法中添加了一个printf(),并在我的iPhone上进行了一些测试运行。日志按预期打印。我的测试代码(包括一个继承自 ASDealloc2MainObject 的新类)是在启用ARC的情况下编译的。


我曾经认为,在ARC下无法完成覆盖保留/释放方法。事实证明我错了。这种技术涉及在MRC下编译的基类及其在ARC下编译的子类。

一个很好的例子是Facebook AsyncDisplayKit。 Facebook AsyncDisplayKit框架中的许多类都继承自名为ASDealloc2MainObject的基类。 ASDealloc2MainObject是一个在MRC下编译并覆盖NSObject的保留/释放方法的类。与此同时,ASDealloc2MainObject的子类在ARC下编译并运行。

我有两个问题:

    互联网上的
  1. Quite a few blog posts表示当ARC在编译期间插入内存管理代码时,它会插入低级C函数,如objc_retain()和objc_release(),而不是它们的Obj-C等价物[NSOject retain ]和[NSObject发布]。 ARC这样做是因为低级别C功能可以提供额外的优化,例如消除昂贵的Obj-C消息发送和取消相邻的自动释放并保留呼叫。我的问题是,如果我们使用MRC / ARC覆盖技术,我们是否会失去这样的优化?
  2. 我的第二个问题在某种程度上与我的第一个问题有关。如果目标对象的基类已覆盖其保留/释放方法,那么objc_retain()/ objc_release()的运行时行为是什么?我的猜测是这些C函数能够弄清楚这里的情况。它们不是执行常规优化(例如消除发送保留/释放消息),而是实际上恢复旧方式并实际发送保留/释放消息。

2 个答案:

答案 0 :(得分:2)

引用文档:

  

只有在定义自己的引用计数方案时,才会实现[retain]方法。此类实现必须返回self,并且不应通过向super发送保留消息来调用继承的方法。

您是否正在实施自己的内存管理系统?没有?然后不要覆盖保留或释放。

Apple还建议不要对所有Objective-C代码使用引用计数。你应该使用ARC。

ASDealloc2MainObject不会覆盖保留或释放。旧版本没有,但FaceBook意识到这是一个糟糕的想法,并更新了他们的代码以使用ARC。

至于ARC究竟是如何表现的,答案是"它取决于"。它有许多不同的表现方式。如果你真的想知道它是如何工作的,请阅读编译器源代码。

您链接的博客文章很古老,根本不值得信任。 Apple每12个月对编译器进行一次重大更改,这意味着自撰写博客文章以来,他们已经完成了3次。由于内存管理是性能瓶颈,因此它们每年都会发生最大的变化。

发送"保留"或"发布"对某个对象的消息非常缓慢。 ARC和Objective-C运行时都尽量避免发送消息。创建Swift语言的原因之一是完全消除发送消息。存在objc_retain()和objc_release()以避免向对象发送保留和释放。可能会有这样的情况,但你不能依赖它。

答案 1 :(得分:0)

我建议您编写一些代码并尝试一下。我希望实际上不会从ARC代码调用retain / release,因为它使用(更快)函数调用。因此,从ARC调用时,您的覆盖将不起作用。它们可能在从非ARC代码调用时起作用。

那是为了找出会发生什么。实际上,在混合ARC /非ARC代码中覆盖保留/释放可能只会让您遇到麻烦。