swiftretain-cycle

swift - retain cycle when calling inner function?


Do I have a retain cycle when inner function progressComplete is calling inside closure without weak self and inside of it (progressComplete) i use self?

class SomeClass{

   var manager = Manager()
   var someVar:Int? 

    func doSomething(completion:((Bool) -> Void)?) {
        
        func progressComplete(_ success:Bool) {
            self.someVar = nil
            completion?(success)
        }
        
        self.manager.requestData { success in
            progressComplete(success)
        }
    }
}

Solution

  • Do I have a retain cycle

    Yes, in the sense that you probably mean it. self (the SomeClass) is retaining the Manager, and the Manager, once doSomething has been called, is retaining the callback method progressComplete which refers to self.

    So, it's not a permanent situation (a true leak), but SomeClass cannot go out of existence until such time as the Manager's requestData has performed its callback. It is easy to confirm this experimentally, and you can see it in the memory graph:

    enter image description here

    That's not necessarily a bad thing! But if it's going to be a problem, then you need to fix it.

    However, note that weak self won't help you here, as there is no place to say it. You can only say weak self in the body of an anonymous function — and you don't have any anonymous functions!

    So the correct way to write this, if you are concerned about it, would be to abandon your separate progressComplete function and write the callback as an anonymous function, and do the weak–strong dance, like this:

        self.manager.requestData { [weak self] success in
            if let self = self {
                self.someVar = nil
                completion?(success)
            }
        }