简体   繁体   English

为什么Objective-C代理通常给予属性赋值而不是保留?

[英]Why are Objective-C delegates usually given the property assign instead of retain?

I'm surfing through the wonderful blog maintained by Scott Stevenson, and I'm trying to understand a fundamental Objective-C concept of assigning delegates the 'assign' property vs 'retain'. 我正在浏览Scott Stevenson维护的精彩博客,我正在尝试理解一个基本的Objective-C概念,即为委托者分配'assign'属性vs'retain'。 Note, the both are the same in a garbage collected environment. 注意,两者在垃圾收集环境中是相同的。 I'm mostly concerned with a non-GC based environment (eg: iPhone). 我主要关注的是非基于GC的环境(例如:iPhone)。

Directly from Scott's blog: 直接来自Scott的博客:

"The assign keyword will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates." “assign关键字将生成一个setter,它直接将值赋给实例变量,而不是复制或保留它。这最适用于NSInteger和CGFloat等原始类型,或者你不直接拥有的对象,如委托。”

What does it mean that you don't directly own the delegate object? 你不直接拥有委​​托对象是什么意思? I typically retain my delegates, because if I don't want them to go away into the abyss, retain will take care of that for me. 我通常会保留我的代表,因为如果我不希望他们离开深渊,保留将为我照顾。 I usually abstract UITableViewController away from its respective dataSource and delegate also. 我通常抽象UITableViewController远离其各自的dataSource和委托。 I also retain that particular object. 我也保留那个特定的对象。 I want to make sure it never goes away so my UITableView always has its delegate around. 我想确保它永远不会消失,所以我的UITableView总是有它的代表。

Can someone further explain where/why I'm wrong, so I can understand this common paradigm in Objective-C 2.0 programming of using the assign property on delegates instead of retain? 有人可以进一步解释我错在哪里/为什么,所以我可以理解Objective-C 2.0编程中使用委托上的assign属性而不是retain的常见范例吗?

Thanks! 谢谢!

The reason that you avoid retaining delegates is that you need to avoid a retain cycle: 您避免保留委托的原因是您需要避免保留周期:

A creates BA sets itself as B's delegate … A is released by its owner A创建BA将自己设置为B的委托...... A由其所有者发布

If B had retained A, A wouldn't be released, as B owns A, thus A's dealloc would never get called, causing both A and B to leak. 如果B保留A,则A不会被释放,因为B拥有A,因此A的dealloc永远不会被调用,导致A和B泄漏。

You shouldn't worry about A going away because it owns B and thus gets rid of it in dealloc. 你不应该担心A会消失,因为它拥有B并因此在dealloc中摆脱它。

Because the object sending the delegate messages does not own the delegate. 因为发送委托消息的对象不拥有委托。

Many times, it's the other way around, as when a controller sets itself as the delegate of a view or window: the controller owns the view/window, so if the view/window owned its delegate, both objects would be owning each other. 很多时候,它是相反的,因为当控制器将自己设置为视图或窗口的委托时:控制器拥有视图/窗口,因此如果视图/窗口拥有其委托,则两个对象将彼此拥有。 This, of course, is a retain cycle, similar to a leak with the same consequence (objects that should be dead remain alive). 当然,这是一个保留周期,类似于具有相同结果的泄漏(应该死的物体保持活着)。

Other times, the objects are peers: neither one owns the other, probably because they are both owned by the same third object. 其他时候,对象是对等的:没有一个拥有另一个,可能是因为它们都由同一个第三个对象拥有。

Either way, the object with the delegate should not retain its delegate. 无论哪种方式,具有委托的对象都不应保留其委托。

(There's at least one exception, by the way. I don't remember what it was, and I don't think there was a good reason for it.) (顺便说一下,至少有一个例外。我不记得它是什么,我认为没有充分的理由。)


Addendum (added 2012-05-19): Under ARC, you should use weak instead of assign . 附录 (2012-05-19添加):在ARC下,你应该使用weak而不是assign Weak references get set to nil automatically when the object dies, eliminating the possibility that the delegating object will end up sending messages to the dead delegate. 当对象死亡时,弱引用被自动设置为nil ,从而消除了委托对象最终向死代表发送消息的可能性。

If you're staying away from ARC for some reason, at least change assign properties that point to objects to unsafe_unretained , which make explicit that this is an unretained but non-zeroing reference to an object. 如果由于某种原因您远离ARC,至少assign指向对象的属性更改为unsafe_unretained ,这明确表明这是对对象的未保留但非归零的引用。

assign remains appropriate for non-object values under both ARC and MRC. assign仍然适用于ARC和MRC下的非对象值。

请注意,当您拥有一个赋值的委托时,每当要释放该对象时,始终将该委托值设置为nil非常重要 - 因此,如果某个对象没有取消分配,那么该对象应该始终小心地在dealloc中取消委托引用在其他地方这样做

One of the reason behind that is to avoid retain cycles. 其中一个原因是避免保留周期。 Just to avoid the scenario where A and B both object reference each other and none of them is released from memory. 只是为了避免A和B两个对象相互引用而且没有一个从内存中释放的场景。

Acutally assign is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates. 对于像NSInteger和CGFloat这样的原始类型,或者你没有直接拥有的对象,例如委托,acutally assign最好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM