简体   繁体   中英

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'. Note, the both are the same in a garbage collected environment. I'm mostly concerned with a non-GC based environment (eg: iPhone).

Directly from Scott's blog:

"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."

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. I also retain that particular object. I want to make sure it never goes away so my UITableView always has its delegate around.

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?

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

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.

You shouldn't worry about A going away because it owns B and thus gets rid of it in 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 . 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.

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.

assign remains appropriate for non-object values under both ARC and 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.

Acutally assign is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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