On Jul 13, 2017, at 02:57 , Jeremy Hughes <moon.rab...@virginmedia.com> wrote: > > When to use unowned rather than weak
Here’s how I understand the situation in Swift. As usual, I may have some things a bit wrong, but I think this is right. There are four kinds of reference variable (or stored property) in Swift: 1. Strong. 2. Weak. 3. Unowned(safe), usually abbreviated to just “unowned”. 4. Unowned(unsafe). Note that these are attributes of the variable (i.e. storage location), not the reference (i.e. pointer). It’s easy to forget that and talk about “strong references” for example, but technically there’s no such thing. “Strong” means that the variable retains its reference. No surprises here. All of the other cases do *not* retain their reference. That is, they do not increment the object’s retain count. But there are other things going on that account for the differences between them. “Weak” means the reference is optional, can be nil, and is automatically set to nil if the referenced object is deallocated. This is safe, because you can’t end up trying to follow an invalid pointer: Swift guarantees that you will see a valid pointer or nil. The downside of “weak” is that a side-table of non-nil weak variable addresses is maintained somewhere, so that weak variables can be nil'ed on deallocation of the referenced object. There is some performance overhead to this, especially as there must obviously be some kind of locking mechanism to provide thread safety. “Unowned” means that the reference is non-optional and can persist after the referenced object is deallocated. This avoids the performance penalty of “weak”, but can’t provide a validity guarantee for the pointer — it’s up to you to keep the object alive for as long as you use the unowned variable’s reference. The clever part, which is specific to Swift, is that objects secretly have *another* retain count, which is the number of *unowned* variable references to the object. An object is not actually deallocated until *both* retain counts go to zero — at which point there are obviously no references to it any more. If you try to use an unowned variable reference while the *main* reference count is zero and the *unowned* reference count is non-zero, you are trying to use a zombie object and your app will immediately crash. Think about this. In effect, all Swift apps have zombie checking on all the time. It’s impossible to use a reference to a non-alive object, and it’s impossible for a stale pointer to refer to an instance of a different class (which can happen in Obj-C if memory is re-allocated for another object while you still hold a pointer to it.) It’s a simple but brilliant idea. It’s pretty cheap, and it crashes as early as possible, which makes debugging easier. What Dave meant, in the things you quoted, is that there’s an overhead to this. Aside from questions of optimization, the overhead is similar to “strong” retain counting. “Unowned(unsafe)” means the same thing as “unretained unsafe” in Obj-C. It’s just a pointer, and you’re responsible for knowing it’s safe to use at any given time. Obviously, you’d like never to see one of these in Swift code. The usage rules for these things are pretty straightforward to state, even though it might be harder in particular cases to be sure what to use. For owning variables, use strong. By default, use weak the rest of the time. If you can reason that a non-owning variable is going to contain a valid reference once initially set (like a “parent” reference in a child object to which the parent has an owning reference in its “children” array, or like an IBOutlet reference, usually), you can avoid the overhead of “weak” and use “unowned” instead. (IIRC, you *must* declare a weak variable as optional, you *must not* declare an unowned variable as optional, but you can declare *either* as implicitly unwrapped optional.) In general, don’t use “unowned(unsafe)”. You should only see it in legacy APIs in the SDKs, where for historical reasons it can’t be declared more definitively as something safer. You might occasionally use it in your own code if the secondary reference counting of “unowned(safe)” happens to be a performance problem. _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com