Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
406 views
in Technique[技术] by (71.8m points)

ios - Is it safe to force unwrap variables that have been optionally accessed in the same line of code?

someFunction(completion: { [weak self] in
    self?.variable = self!.otherVariable
})

Is this always safe? I access the optional self in the beginning of the statement, and personally I assume that the second part of this statement will never be executed if self is nil. Is this true? If self indeed is nil, the second part will never happen? And it will never happen that self could be 'nilled' during this single line of code?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...