swiftclosuresweak-references

In Swift, if I have a closure capturing [weak self], is it good practice to unwrap the optional self at the beginning of the closure?


I am using Swift for a macOS application, Xcode is 12.5.1. Imagine I have the following code:

func performAsyncTask(completion: { [weak self] (error: Error?) in 

     self?.someProperty = 0.0
     self?.someOtherProperty = 0.0
     // Other similar statements follow
})

Is it good choice to change it to:

func performAsyncTask(completion: { [weak self] (error: Error?) in 
     
     guard let self = self else { return }
     self.someProperty = 0.0
     self.someOtherProperty = 0.0
     // Other similar statements follow
})

I believe that the first implementation is better because self could become nil between the statements, so unwrapping at the beginning could be less clean. I hope an expert can bring me in the right direction. Thanks for your attention.


Solution

  • I believe that the first implementation is better because self could become nil between the statements

    And that's why the second implementation is in fact better! If self is not nil at the first statement, the first statement makes it so that self couldn't become nil between the statements. It retains self exactly for the remainder of the block. This is called "the weak–strong dance".

    guard let self = self else { return }
          //  ^^^^ this self is _strong_, not weak; it retains self
    

    Edit: Note that in modern Swift it is sufficient to say

    guard let self else { return }