Optional Chaining
from "The Swift Programming Language"
gives the following example:
let john = Person()
// ...
let someAddress = Address()
// ...
john.residence?.address = someAddress
followed by (emphasis added):
In this example, the attempt to set the address property of john.residence will fail, because john.residence is currently nil.
The assignment is part of the optional chaining, which means none of the code on the right hand side of the = operator is evaluated.
Applied to your case: In
self?.variable = self!.otherVariable
the right-hand side is not evaluated if self
is nil
.
Therefore the answer to your question
If self indeed is nil, the second part will never happen?
is "yes". With regard to the second question
And it will never happen that self could be 'nilled' during this single line of code?
My original assumption was that once self
has been determined to be != nil
,
a strong reference to self!
is held throughout the evaluation of the
statement, so that this can not happen. However (as @Hamish pointed out),
this is not guaranteed. Apple engineer Joe Groff writes at Confirming order of operations in
the Swift forum:
This isn't guaranteed. Releases may be optimized to happen earlier than this, to any point after the last formal use of the strong reference. Since the strong reference loaded in order to evaluate the left-hand side weakProperty?.variable
is not used afterward, there is nothing keeping it alive, so it could be immediately released.
If there are any side effects in the getter for variable that cause the object referenced by weakProperty
to be deallocated, nil-ing out the weak reference, then that would cause the force-unwrap on the right side to fail.
You should use if let to test the weak reference, and reference the strong reference bound by the if let
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…