我正在浏览Scott Stevenson维护的精彩博客,并且我正在尝试理解一个基本的Objective-C概念,即为委托人分配'assign'属性vs'retain'。注意,两者在垃圾收集环境中是相同的。我主要关注的是非基于GC的环境(例如:iPhone)。
直接来自Scott的博客:
“assign关键字将生成一个setter,它直接将值赋给实例变量,而不是复制或保留它。这最适用于NSInteger和CGFloat等原始类型,或者您不直接拥有的对象,如代表“。
您不直接拥有委托对象是什么意思?我通常会保留我的代表,因为如果我不希望他们离开深渊,保留将为我照顾。我通常抽象UITableViewController远离其各自的dataSource和委托。我也保留那个特定的对象。我想确保它永远不会消失,所以我的UITableView总是有代表。
有人可以进一步解释我错在哪里/为什么错,所以我可以理解Objective-C 2.0编程中使用委托的assign属性而不是retain的常见范例吗?
谢谢!
答案 0 :(得分:175)
您避免保留代表的原因是您需要避免保留周期:
A创造B A将自己设置为B的委托 ... A由其所有者发布
如果B保留A,则A不会被释放,因为B拥有A,因此A的dealloc永远不会被调用,导致 A和B 泄漏。
你不应该担心A会消失,因为它拥有B并因此在dealloc中摆脱它。
答案 1 :(得分:44)
因为发送委托消息的对象不拥有委托。
很多时候,它是相反的,因为当控制器将自己设置为视图或窗口的委托时:控制器拥有视图/窗口,因此如果视图/窗口拥有其委托,则两个对象都将拥有彼此。当然,这是一个保留周期,类似于具有相同结果的泄漏(应该死的物体保持活着)。
其他时候,对象是对等的:没有一个拥有另一个,可能是因为它们都归同一个第三个对象所有。
无论哪种方式,具有委托的对象都不应保留其委托。
(顺便说一下,至少有一个例外。我不记得它是什么,我认为没有充分的理由。)
附录(已添加2012-05-19):在ARC下,您应使用weak
代替assign
。当对象死亡时,弱引用自动设置为nil
,从而消除了委托对象最终向死代表发送消息的可能性。
如果您出于某种原因远离ARC,至少将指向对象的assign
属性更改为unsafe_unretained
,这明确表明这是一个未保留但非归零的引用对象
assign
仍适用于ARC和MRC下的非对象值。
答案 2 :(得分:17)
请注意,当您拥有一个赋值的委托时,每当要释放该对象时始终将该委托值设置为nil非常重要 - 因此对象应始终小心地在dealloc中取消委托引用它没有在其他地方这样做过。
答案 3 :(得分:1)
其中一个原因是避免保留周期。 只是为了避免A和B两个对象相互引用而且没有一个从内存中释放的场景。
Acutally assign 最适合原始类型,如NSInteger和CGFloat,或者您不直接拥有的对象,例如委托。