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

Reply via email to