我正在浏览由 Scott Stevenson 维护的精彩博客,我试图理解一个基本的 Objective-C 概念,即为代表分配“分配”属性与“保留”。请注意,两者在垃圾收集环境中是相同的。我最关心的是基于非 GC 的环境(例如:iPhone)。
直接来自 Scott 的博客:
“assign 关键字将生成一个 setter,它直接将值分配给实例变量,而不是复制或保留它。这最适用于 NSInteger 和 CGFloat 等原始类型,或者您不直接拥有的对象,例如委托。”
您不直接拥有委托对象是什么意思?我通常会保留我的代表,因为如果我不希望他们陷入深渊,保留会为我解决这个问题。我通常将 UITableViewController 从其各自的数据源和委托中抽象出来。我也保留了那个特定的对象。我想确保它永远不会消失,所以我的 UITableView 总是有它的委托。
有人可以进一步解释我在哪里/为什么错了,这样我就可以理解 Objective-C 2.0 编程中使用委托而不是保留的分配属性的常见范例?
谢谢!
避免保留代表的原因是您需要避免保留周期:
A 创建 BA 将自己设置为 B 的代表…… A 由其所有者释放
如果 B 保留了 A,A 将不会被释放,因为 B 拥有 A,因此 A 的 dealloc 将永远不会被调用,从而导致 A 和 B 都泄漏。
您不应该担心 A 会消失,因为它拥有 B 并因此在 dealloc 中摆脱了它。
因为发送委托消息的对象并不拥有委托。
很多时候,情况正好相反,例如当控制器将自己设置为视图或窗口的委托时:控制器拥有视图/窗口,因此如果视图/窗口拥有它的委托,则两个对象将相互拥有。当然,这是一个保留循环,类似于具有相同后果的泄漏(应该死的对象仍然活着)。
其他时候,对象是对等的:没有一个拥有另一个,可能是因为它们都属于同一个第三个对象。
无论哪种方式,具有委托的对象都不应保留其委托。
(顺便说一句,至少有一个例外。我不记得是什么,而且我认为没有充分的理由。)
附录(2012 年 5 月 19 日添加):在 ARC 下,您应该使用 weak
而不是 assign
。当对象死亡时,弱引用会自动设置为 nil
,从而消除委托对象最终将消息发送给死亡委托的可能性。
如果您出于某种原因远离 ARC,至少将指向对象的 assign
属性更改为 unsafe_unretained
,这明确表明这是对对象的未保留但非归零的引用。
assign
仍然适用于 ARC 和 MRC 下的非对象值。
NSURLConnection
保留其委托。
weak
,但这并不能回答最初的问题:为什么 Apple 使用 assign
而不是 weak
?
assign
而不是 retain ”;询问时 weak
不存在。您的问题是另一个问题,您应该单独提出。我很乐意回答。
请注意,当您有一个要分配的委托时,无论何时要解除分配对象,始终将该委托值设置为 nil 非常重要 - 因此,如果对象没有,则应始终小心在 dealloc 中将委托引用归零在其他地方这样做。
其背后的原因之一是避免保留周期。只是为了避免 A 和 B 两个对象相互引用并且它们都没有从内存中释放的情况。
Acutally assign 最适合原始类型,如 NSInteger 和 CGFloat,或您不直接拥有的对象,如委托。
weak
所做的吗?问题是为什么使用assign
而不是weak
?assign
而不是retain
。这个问题比 ARC 更老;weak
和strong
(后者是retain
的同义词)直到 ARC 被引入才存在。您应该分别询问有关weak
与assign
的问题。