为什么 Objective-C 委托通常给予财产转让而不是保留?

我正在浏览 Scott Stevenson 维护的精彩博客,并试图理解 Objective-C 的一个基本概念,即分配委托的“分配”属性与“保留”属性。注意,在垃圾回收环境中,两者是相同的。我最关心的是一个非 GC 环境(例如: iPhone)。

直接来自 Scott 的博客:

”赋值关键字将生成一个 setter,它直接将值赋给实例变量,而不是复制或保留它。这对于 NSInteger 和 CGFloat 这样的基本类型,或者您不直接拥有的对象(如委托)来说是最好的。”

不直接拥有委托对象是什么意思?我通常会保留我的代表,因为如果我不想让他们走向深渊,保留就会帮我解决这个问题。我通常将 UITableViewController 从其各自的 dataSource 中抽象出来,并且也进行委托。我还保留着那件特别的物品。我想确保它永远不会消失,所以我的 UITableView 总是有它的代表在身边。

有没有人可以进一步解释一下我错在哪里/为什么错在哪里,这样我就可以理解 Objective-C 2.0编程中使用委托上的分配属性而不是保留的常见范例?

谢谢!

47023 次浏览

你避免保留代表的原因是,你需要避免一个保留代表的周期:

A 创造了 B A 将自己设置为 B 的委托 ... A 由其所有者释放

如果 B 保留了 A,那么 A 将不会被释放,因为 B 拥有 A,因此 A 的 deloc 将永远不会被调用,从而导致 A 和 B 都是泄漏。

你不应该担心 A 会离开,因为它拥有 B,因此会在 dealloc 中抛弃它。

因为发送委托消息的对象不拥有该委托。

很多时候,情况恰恰相反,比如当控制器将自己设置为视图或窗口的委托时: 控制器拥有视图/窗口,所以如果视图/窗口拥有自己的委托,那么两个对象就会相互拥有对方。当然,这是一个保留循环,类似于具有相同后果的泄漏(应该死亡的对象仍然活着)。

其他时候,对象是对等对象: 两者都不拥有对方,可能是因为它们都属于同一第三个对象。

无论采用哪种方式,具有委托的对象都不应保留其委托。

(顺便说一句,至少有一个例外。我不记得那是什么,我也不认为有什么好的理由。)


附录 (2012-05-19) : 在 ARC 下,应该使用 weak而不是 assign。弱引用在对象死亡时自动设置为 nil,从而消除了委托对象最终向死亡委托发送消息的可能性。

如果出于某种原因而远离 ARC,那么至少将指向对象的 assign属性更改为 unsafe_unretained,这将明确表示这是对对象的未保留但未归零的引用。

assign仍然适用于 ARC 和 MRC 下的非对象值。

请注意,当您有一个委托被赋值时,无论何时将要释放对象时,始终将该委托值设置为 nil 是非常重要的——因此,如果对象没有在其他地方这样做,则应始终小心地在 deloc 中将委托引用设置为 nil。

这背后的原因之一是为了避免保留周期。 只是为了避免这样的场景: A 和 B 对象相互引用,而且没有一个对象从内存中释放。

实际上,分配最适合于 NSInteger 和 CGFloat 等基本类型,或者不直接拥有的对象,如委托。