委托中的属性"assign"和"retain"的含义

16

iOS开发中,委托(delegate)几乎被广泛应用。

对于像这样的委托,我们需要使用 "assign" 而不是 "retain"。

@property(assign) id delegate;
避免循环引用问题是原因。为什么Objective-C代理通常使用属性assign而不是retain? 我看到很多代码仍在使用“retain”。那么这里的问题是,如果我们为委托使用retain,我们是否仍会遇到循环引用问题?
谢谢。
1个回答

26

文档中提到:

保留一个对象会创建一个强引用,只有在所有的强引用被释放之后该对象才能被释放。如果两个对象互相保留,它们中的任何一个都无法被释放,因为它们之间的连接无法被断开。

例如,考虑一个实现了 UITableViewDelegate 协议的 UITableViewController。UITableView 被它的视图控制器持有,尽管 UITableView 不保留它的代理。

如上所述的文档,UITableViewController 只有在所有强引用被释放时才能完成其析构。由于将 UITableViewController 作为代理的UITableView不保留它,当UItableViewController 的拥有者调用 release 方法时,引用计数将变为零并且 dealloc 方法将被调用。

现在假设 UITableView 保留它的代理。UITableViewController 将至少具有 +2 的保留计数。一种来自它的拥有者,另一种来自 UITableView。当 UITableViewController 的拥有者对其调用 release 方法时,引用计数将变为 +1,并且不像预期的那样降为零,因此 dealloc 方法直到引用计数达到零时才会被调用。要使引用计数达到零,UITableViewController 需要释放它的 UITableView,然后UITableView 将释放它的代理 (UITableViewController)。因为 UITableViewController 只有在 dealloc 时才会处理它的视图 (UITableView),而此时这种情况永远不会发生,因为保留计数不会降至 +1 以下。

(让我们不考虑内存警告和任何其他可能的情况...我只是注意到 ViewController / View 不是此示例的最佳选项,但我已经写了太多了。 :))

这有意义吗?


是的,非常有意义,非常感谢!在您的情况下,A 是 UITableViewController,B 是 TableView,所以唯一正确的方法是在 TableView 中使用“assign”来分配委托。考虑另一个常见情况,A 是 ViewController,B 是另一个 ViewController,A 创建了一个新的 B,并在 B 中使用“retain”作为委托,同时 A 可以释放 B,因此在这种情况下,在 B 中使用“retain”作为委托是可以的。这有意义吗? - Forrest
没听懂。你说A创建B,A将B用作某些东西的代理,因此,A.viewController(保留)= B,而A.delegate(分配)= B。还是A是B上的代理,因此,A.viewController(保留)= B,而B.delegate(分配)= A?哪种情况是正确的? - vfn
为什么Objective-C代理通常使用属性assign而不是retain?A和B的上下文来自链接。 - Forrest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接