Re: Who owns a child view controller?
Re: Who owns a child view controller?
- Subject: Re: Who owns a child view controller?
- From: Quincey Morris <email@hidden>
- Date: Thu, 13 Jul 2017 11:43:42 -0700
On Jul 13, 2017, at 02:57 , Jeremy Hughes <email@hidden> 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 (email@hidden)
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:
This email sent to email@hidden