I understand the usage and superficial differences between weak
and unowned
in Swift:
The simplest examples I\'ve seen is that if there is
My question is, what is the point in having two such similar concepts? What are the internal differences that necessitate having two keywords for what seem essentially 99% the same thing?
They are not at all similar. They are as different as they can be.
weak
is a highly complex concept, introduced when ARC was introduced. It performs the near-miraculous task of allowing you to prevent a retain a cycle (by avoiding a strong reference) without risking a crash from a dangling pointer when the referenced object goes out of existence — something that used to happen all the time before ARC was introduced.
unowned
, on the other hand, is non-ARC weak (to be specific, it is the same as non-ARC assign
). It is what we used to have to risk, it is what caused so many crashes, before ARC was introduced. It is highly dangerous, because you can get a dangling pointer and a crash if the referenced object goes out of existence.
The reason for the difference is that weak
, in order to perform its miracle, involves a lot of extra overhead for the runtime, inserted behind the scenes by the compiler. weak
references are memory-managed for you. In particular, the runtime must maintain a scratchpad of all references marked in this way, keeping track of them so that if an object weakly referenced goes out of existence, the runtime can locate that reference and replace it by nil
to prevent a dangling pointer.
In Swift, as a consequence, a weak
reference is always to an Optional (exactly so that it can be replaced by nil
). This is an additional source of overhead, because working with an Optional entails extra work, as it must always be unwrapped in order to get anything done with it.
For this reason, unowned
is always to be preferred wherever it is applicable. But never use it unless it is absolutely safe to do so! With unowned
, you are throwing away automatic memory management and safety. You are deliberately reverting to the bad old days before ARC.
In my usage, the common case arises in situations where a closure needs a capture list involving self
in order to avoid a retain cycle. In such a situation, it is almost always possible to say [unowned self]
in the capture list. When we do:
It is more convenient for the programmer because there is nothing to unwrap. [weak self]
would be an Optional in need of unwrapping in order to use it.
It is more efficient, partly for the same reason (unwrapping always adds an extra level of indirection) and partly because it is one fewer weak reference for the runtime's scratchpad list to keep track of.
A weak
reference is actually set to nil and you must check it when the referent deallocates and an unowned
one is set to nil, but you are not forced to check it.
You can check a weak
against nil with if let
, guard
, ?
, etc, but it makes no sense to check an unowned
, because you think that is impossible. If you are wrong, you crash.
I have found that in-practice, I never use unowned. There is a minuscule performance penalty, but the extra safety from using weak is worth it to me.
I would leave unowned usage to very specific code that needs to be optimized, not general app code.
The "why does it exist" that you are looking for is that Swift is meant to be able to write system code (like OS kernels) and if they didn't have the most basic primitives with no extra behavior, they could not do that.
NOTE: I had previously said in this answer that unowned is not set to nil. That is wrong, a bare unowned
is set to nil. A unowned(unsafe)
is not set to nil and could be a dangling pointer. This is for high-performance needs and should generally not be in application code.