Apple's Swift Programming Language Guide mentions the capture specifiers unowned(safe)
and unowned(unsafe)
, in addition to weak
and unowned
.
I (think I) understand the differences between weak
and unowned
; but what is the difference between unowned(safe)
and unowned(unsafe)
? The guide doesn't say.
Please: Don't rely on simply stating an Objective-C equivalent.
From what I understand, although I can't find a definitive source from Apple, unowned
can be broken into two flavors, safe
and unsafe
.
A bare unowned
is unowned(safe)
: it is a specially wrapped reference which will throw an exception when a dealloced instance is referenced.
The special case is unowned(unsafe)
: it is the Swift equivalent of Objective C's @property (assign)
or __unsafe_unretained
. It should not be used in a Swift program, because its purpose is to bridge to code written in Objective C.
So, you will see unowned(unsafe)
when looking at the import wrapper for Cocoa classes, but don't use it unless you have to, and you will know when you have to.
Update
__unsafe_unretained
is a simple pointer. It will not know when the instance being pointed at has be dealloced, so when it's dereferenced, the underlying memory could be garbage.
If you have a defect where a dealloced __unsafe_unretained
variable is being used, you will see erratic behavior. Sometimes enough of that memory location is good enough so the code will run, sometimes it will have been partially overwritten so you will get very odd crashes, and sometimes that memory location will contain a new object so you will get unrecognized selector exceptions.
Transitioning to ARC Release Notes
__unsafe_unretained
specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling.
Here is a quote from Apple Developer Forums:
unowned
vs unowned(safe)
vs unowned(unsafe)
unowned(safe)
is a non-owning reference that asserts on access that
the object is still alive. It's sort of like a weak optional reference
that's implicitly unwrapped with x!
every time it's accessed.
unowned(unsafe)
is like __unsafe_unretained
in ARC—it's a non-owning
reference, but there's no runtime check that the object is still alive
on access, so dangling references will reach into garbage memory.
unowned
is always a synonym for unowned(safe)
currently, but the
intent is that it will be optimized to unowned(unsafe)
in -Ofast
builds when runtime checks are disabled.
Variable is accessed when it was dellocated already with attribute:
unowned
- Program knows it is invalid, and goes crash immediately.
- Behavior is defined.
unowned(unsafe)
- Program knows nothing.
- It may crash immediately.
- It may access unknown memory address and have strange state until it it dies at surprise location.
- Behavior is undefined. Life gets harder.
A simple Definition. which would clear the confusion.
-- unowned attributes : If you try to access an unowned reference after the instance that it refers to is deallocated, your program will crash.
-- unowned(Unsafe) attributes: If you try to access an unsafe unowned reference after the instance that it refers to is deallocated, your program will try to access the memory location where the instance used to be, which is an unsafe operation. (no guarantee wether this would executes or crashes)