Is it the right way using `[weak self]` in swift closure?

James Zhang

I always using [weak self] in swift closure to prevent reference cycle. Here is the code below, is it the correct way?

someTask(completion: {[weak self] (result) in
        if self == nil {  
            return
        }

        //is it safe when reach here? 

        self!.xxx = yyy
        self!.doLongTermWork()
        self!.finish()  //will crash when self is nil?
    })

Weak self does not keep a strong hold on the instance. So when self.doLongTermWork(), will self be set to nil again somewhere else?

Rob

Your pattern has race condition. If self was deallocated at the exact same time as your completion handler closure was executing, it could crash. As a general rule, avoid using the ! forced unwrapping operator if you can.

  1. I’d lean towards the guard “early exit” pattern (reducing nested braces, making code easier to read). The standard Swift 4.2 solution is:

    someTask { [weak self] result in
        guard let self = self else { return }
    
        self.xxx = yyy
        self.doLongTermWork()
        self.finish()
    }
    
  2. Before Swift 4.2, which implemented SE-0079, we would have to do something like:

    someTask { [weak self] result in
        guard let strongSelf = self else { return }
    
        strongSelf.xxx = yyy
        strongSelf.doLongTermWork()
        strongSelf.finish()
    }
    

    You can see why we prefer the Swift 4.2 improvement, as this strongSelf syntax is inelegant.

  3. The other obvious alternative is just:

    someTask { [weak self] result in
        self?.xxx = yyy
        self?.doLongTermWork()
        self?.finish()
    }
    

    Sometimes you need the “weak self - strong self dance” (the first two alternatives), but it would not appear to be the case here. This is likely sufficient.

There are other scenarios/edge cases that one might contemplate, but these are the basic approaches.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

weak self in gcd in swift closure

Weak self vs self when using closure defined in swift in objective c

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?

Is there a way to show warning on not using weak self?

Are there potential drawbacks to using a [weak self] within a closure after declaring a strong self?

Swift - weak self in didSet

Swift: should completion closure have error indication when weak self is nil?

Why [weak self] is not required for @nonescaping closure?

Is weak self needed in NSKeyValueObservation observe() closure?

`self` in Swift closure

Swift: Maintaining atomicity in a block-based execution using weak self

Make self weak in methods in Swift

How to set a weak reference to a closure/function in Swift?

Swift - `self` in variable initialization closure

Why Swift closure not capture self?

Should I use weak self inside a computed property's closure?

Swift closures [weak self] and async tasks

Swift guarding weak self for nested callbacks

Swift closure syntax using { ... in }

Is there any way to persist a Swift closure?

When to use [self] vs [weak self] in swift blocks?

Break Swift closure retain circle with not weak explicit capture

Using weak self in dispatch_async function

Add [unowned self] to the closure argument Swift

"__weak MyClass *myWeakClass = self" using myWeakClass VS using self

Is this function right? Call a function with closure (swift - iOS)

Does using a function as a closure retain self?

How to prevent memory leak with using self in closure

Objective-C: Should we use weak self within block or assign weak self to strong before using it?