【问题标题】:Adding a weak ivar to a Objective-C class using the runtime使用运行时将弱 ivar 添加到 Objective-C 类
【发布时间】:2012-07-21 17:26:01
【问题描述】:

是否可以向使用运行时创建的类添加归零弱引用(在 ARC 意义上,而不是 GC)实例变量?如果有怎么办?

有一个名为class_setWeakIvarLayout() 的函数似乎与此相关,但不幸的是,文档(对于此函数和非弱对应项)非常很薄。

【问题讨论】:

    标签: objective-c automatic-ref-counting weak-references objective-c-runtime


    【解决方案1】:

    您可以使用具有容器类的关联引用来实现归零弱引用。基本上:

    1. 您的容器类包含一个 ivar,声明为 __weak id
    2. 关联引用“setter”创建一个容器,将__weak id ivar 设置为指向您的对象,然后使用objc_setAssociatedObjects(self,&key,container,OBJC_ASSOCIATION_RETAIN) 存储容器
    3. 您的 getter 使用 objc_getAssociatedObject(self, &key) 检索容器并返回 __weak id ivar。如果您的对象已被dealloc'ed,则容器的__weak id ivar 将为零。

    【讨论】:

    • 如果你想要一个弱引用,OBJC_ASSOCIATION_RETAIN 不应该是 OBJC_ASSOCIATION_ASSIGN 吗?
    • 当容器是 NSProxy 子类时,这看起来很不错。
    • 另见stackoverflow.com/questions/16569840/…,其中有示例代码。
    【解决方案2】:

    class_setWeakIvarLayout() 在 GC 下使用。我不确定它是否在 ARC 下使用。在任何情况下,您都无法在运行时更改类的布局,包括添加任意实例变量(尽管由于现代运行时,您可以将 ivars 添加到类并重新编译而无需重新编译子类)。

    请参阅关联对象。它们提供了您想要的大部分,也许是全部(我不确定是否直接支持 zeroing-weak - 不,您需要找到替代解决方案)。

    http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocAssociativeReferences.html


    啊——好的。感谢您的澄清。我不确定您是否可以通过 API 动态设置弱调零 ARC 行为。不过,运行时和编译器的源代码是可用的。

    请注意,您可以很容易地在非 ARC 环境下伪造归零弱,方法是设置一个实现 -dealloc 的类来执行您需要的任何清理,将实例与需要在释放时触发所述清理的对象相关联,并确保没有别的保留具有自定义 -dealloc 通知挂钩的对象。它有点脆弱,但它可以工作。

    【讨论】:

    • 感谢您的回答!我知道您在注册课程后无法更改课程。这适用于使用 objc_allocateClassPair() 创建的完全自定义的类。可悲的是 OBJC_ASSOCIATION_ASSIGN 只是弱而不是归零弱(使用一个小练习进行测试),所以我实际上试图通过添加一个 ivar 来找到一个替代解决方案:)
    • @frenetischapplaudierend:除了 bbum 的最后一段,Mike Ash 有 an article about creating your own zeroing weak references,你可能会感兴趣。
    • Josh 和 bbum,感谢您的帮助。现在我可能只保留一个关联对象,直到它成为非归零弱引用的问题。只是希望有一种简单的方法可以正确地做到这一点。不过会看看 Mike Ashs 的实现,它看起来很有希望!
    • 好的,我很好奇,并按照 bbum 的建议在 objc 运行时源中进行了搜索。事实证明,您可以制作自己的 __weak ivars。关键是 class_setWeakIvarLayout() 函数,但它的文档严重缺乏,即使在源代码中也是如此。我会尝试在答案中解释它。
    • 好的,下次在兴奋之前进行更多研究......虽然在 object_setIvar() 期间似乎为 ARR 类咨询了 class_setWeakIvarLayout(),但在编译该类之前是否启用了 ARR 会进行检查。对于通过运行时函数添加的类,此测试将失败,所以仍然回到我原来的位置......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多