As Apple said in "The Swift Programming Language", it seems we should prefer unowned
than weak
whenever possible:
If the captured reference will never become nil, it should always be captured as an unowned reference, rather than a weak reference.
From the "Weak and Unowned References" section on this page
I did know the difference between these two. But I am curious about is there any good reason for preferring unowned
than weak
? I think the weak
is much safer and we can just always write [weak obj]
and an optional binding check without thinking the possibility of existing of the obj
.
Is it related to some performance consideration or something I missed? Or is it totally ok to use weak
instead of unowned
all the time?
Weak references are automatically set to nil
once the object they point to gets deallocated. For this to be possible in Swift, those must be declared as var
and optional:
class SomeOtherClass {
weak var weakProperty: SomeClass?
}
This is fine if the weakProperty
can become nil
while the instance of SomeOtherClass
is still alive and we want to check for that before using it (delegates are one such example). But what if some reference should never logically be nil
and we still want to prevent a retain cycle? In Objective-C any object reference can be nil
(and messaging nil
always fails silently) so there is no dilemma, we always use weak
. But Swift doesn't have nilable references at all. We use optionals for something that can semantically lack value. But we shouldn't be forced to use optionals for something that must always have value, just to be able to break a retain cycle. Such practice would go against the intended semantics of optionals.
That's where unowned
comes in. It comes in two flavours - unowned(safe)
and unowned(unsafe)
. The latter is dangerous and it's equivalent to assign
and unsafe_unretained
from Objective-C. But the former, which is the default one (at least while debugging; not sure if they optimise it to unowned(unsafe)
in release builds), will reliably crash your app if the referenced object gets prematurely deallocated. Sure, your app will crash if something goes wrong, but that's much easier to debug than failing silently. It should only fail silently when you actually want that (in which case you would use weak
)
Swift strong, weak, unowned reference
[Objective-C property attributes]
ARC
- Automatic Reference Counting
is a mechanism which manages a memory, which is applicable for reference
type[About]. An object is deallocated only when there are 0 references on it.
Strong reference
- is set by default and it is safe to use this type in a linear relationships(there is no loop)
Retain cycle
- it is a situation when each of who objects has a strong reference on each other
Break a Retain cycle
: weak
and unowned
. Both of them does not increase an object's retain count by +1
, and have next differences
Weak reference
- When a references object is deallocated(is nil
), ARC
set a weak
reference to nil
too. That is why weak
reference is a variable var
(can not be a constant let
)[var vs let] and that is why it is an optional
weak var delegate: <Type>?
GENERAL
unowned
- When a references object is deallocated(is nil
), the unowned
does not become a nil
because ARC
does not set it. That is why unowned
reference is non-optional
unowned(by default)
safe unowned
- uses runtime safety check
to throw an exception if unowned
reference was deallocated.
Fatal error: Attempted to read an unowned reference but object 0x7fa5dad3f0f0 was already deallocated
unowned(unsafe)
unowned(unsafe)
operates by UnsafePointer
that can create a dangling pointer
. __unsafe_unretained
from Objective-C
. It is a kind of direct memory access which ARC
does not handle. It can produce unexpected behaviour, not just some crash. It has better performance
EXC_BAD_ACCESS
[EXC_BAD_ACCESS]
[Closure sample]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With