使用 ARC 并针对 iOS 4.0 时如何替换弱引用?

Posted

技术标签:

【中文标题】使用 ARC 并针对 iOS 4.0 时如何替换弱引用?【英文标题】:How do I replace weak references when using ARC and targeting iOS 4.0? 【发布时间】:2011-10-17 02:35:02 【问题描述】:

我已经开始使用 Xcode 4.2 开发我的第一个 ios 应用程序,并以 iOS 5.0 为目标,使用“实用程序”模板(带有 FlipsideViewController 的模板)。

我读到由于 ARC 是一个编译时特性,它也应该与 iOS 4 兼容,所以我尝试将我的应用程序定位到 4.3,并尝试编译它。当我这样做时,我收到此错误:

FlipsideViewController.m:错误:自动引用计数问题:当前部署目标不支持自动 __weak 引用

它引用了这一行:

@synthesize delegate = _delegate;

该变量声明为:

@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;

我知道 iOS 4 不支持“弱引用”,但我真的不明白为什么要使用弱引用开始,我也不知道如何重写东西以避免使用它,同时仍然利用 ARC(毕竟,它应该适用于 iOS 4 和 5 对吧?)

【问题讨论】:

【参考方案1】:

要针对较旧的操作系统,您可以在属性声明中使用unsafe_unretained 而不是weak,它应该以相同的方式工作。 weak 在目标消失时引用 nil 本身,但 unsafe_unretained 留下了您所链接的对象在释放时可能变成悬空指针的可能性。后者与您在手动内存管理中使用 assign 作为属性声明的行为相同。

您这样做是为了避免保留周期,我在回答 here 中提到了这一点。您不希望有一个指向可能具有指向原始对象的强指针的东西的强指针。然后什么都不会被正确释放。

【讨论】:

感谢您的建议。你说“以旧操作系统为目标......”。这是否意味着我应该只在 5.0 之前的应用程序版本中使用 unsafe_unretained?或者我可以只在我的代码中使用 unsafe_unretained,并将其构建为针对 4.x 和 5.x 吗? @Mason - iOS 4.x 和 5.0 都支持unsafe_unretained,因此它为您提供了向后兼容性。如果您正在执行仅 5.0 的构建,则可以切换到 weak 以利用它为您提供的额外安全性。 我尝试了 unsafe_unretained,它仍然有效。但是,我收到了很多警告,例如 '"** __NSAutoreleaseNoPool(): Object 0x564bd90 of class __NSArrayM autoreleased with no pool in place - just leaking"* ',这很正常吗? @fifth - 这是一个完全不相关的问题。您在没有自动释放池的情况下在后台线程上运行某些东西。手动创建的线程没有自己的自动释放池,因此您需要使用 @autoreleasepool 自己创建一个(在 ARC 下,NSAutoreleasePool 用于较旧的手动引用计数实现)。 @Brad,这很有帮助,警告消失了,我接到了几个 performSelectorInBackground 调用。【参考方案2】:

如果仅使用弱引用来提高安全性,则手动调用新的运行时函数(如果它们可用),如果不可用,则回退到对 __unsafe_unretained 变量的简单赋值。

ZWRCompatibility.h 会稍微简化一下。

【讨论】:

【参考方案3】:

感谢 Mike Ash 的兼容性库 PLWeakCompatibilty,您现在也可以在 iOS 4.x 上简单地使用 __weak。

它非常容易配置,并且不需要超过 5.x 的额外考虑或努力。

【讨论】:

以上是关于使用 ARC 并针对 iOS 4.0 时如何替换弱引用?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ARC 下的 Objective-C 上零弱引用为零时得到通知?

总是将 self 的弱引用传递到 ARC 中的块中?

iOS 4 真的支持 ARC 吗? iOS 4.2 SDK 在链接时缺少与 ARC 相关的符号

Objective-C——强引用弱引用(StrongWeak)

我们可以在 ARC 中为弱属性使用 self.prefix 名称吗

Swift学习笔记-自动引用计数弱引用和无主引用