简体   繁体   中英

Swift: self reference in nested closures

I am using the new block based KVO API in Swift to observe properties. Below is the sample code.

class A: NSObject {
var observerA: NSKeyValueObservation? = nil
var observerB: NSKeyValueObservation? = nil

var property1: CustomObj1?
var property2: CustomObj2?

func doSomething() {

}

func doSomethingElse() {

}

func observeValues() {
    observerA = customObj1.observe(\.property1, options: [], changeHandler: { [weak self] (obj, change) in
        guard let strongSelf = self else { return }
        strongSelf.doSomething()
        strongSelf.observerB = customObj2.observe(\.property2, options: [], changeHandler: { [weak strongSelf] (nestedObj, nestedChange) in
            guard let nestedStrongSelf = strongSelf else { return }
            nestedStrongSelf.doSomethingElse()
        })
    })
}

}

My question is how do we refer to self in the inner change handler block. I could use it as it above and I don't see any memory leaks. But using self in place of strongSelf in "[weak strongSelf]" within inner change handler also does not cause any issues. Here is the code.

func observeValues() {
observerA = self.observe(\.property1, options: [], changeHandler: { [weak self] (obj, change) in
    guard let strongSelf = self else { return }
    strongSelf.doSomething()
    strongSelf.observerB = strongSelf.observe(\.property2, options: [], changeHandler: { [weak self] (nestedObj, nestedChange) in
        guard let nestedStrongSelf = self else { return }
        nestedStrongSelf.doSomethingElse()
    })
})

}

My question is how should self be referred within nested completion handlers and what should be the best practice in this. Thanks.

You won't see any memory leaks, even if you had a strong reference cycle, until all other strong references disappear.

For example, if this VC is alive for the whole app lifetime, even if a closure was capturing a strong reference cycle, it wouldn't do anything. The impact would be the same: the VC would be alive for the whole app lifetime, which it was already doing anyway.

You would be able to identify a memory leak only if you had a strong reference cycle, and then tried deinitializing the VC by deleting all other strong refs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM