XM Zhang
XM Zhang

Reputation: 123

About strong reference cycles for closures in Swift

I have defined a class called Person. This is my code:

    class Person { 
        var closure: (() -> ())?
        var name: String

        init(name: String) {

            self.name = name
            print("\(name) is being initialized")
        }

        deinit {
            print("\(name) is being deinitialized")
        }
    }

then I use Person in class called ViewController:

class ViewController: UIViewController {

    var person = Person(name: "john")
    let aStr = "john is a cute boy"


    override func viewDidLoad() {
        super.viewDidLoad()

        person.closure = {
            print("\(self.aStr)")
        }
        person.closure!()
    }
}

In my opinion, the picture of memory about my code like this : memory

So, from above picture, in my opinion, it will cause strong reference cycle between the three instances, but I can not get any leak from Instruments, so I have some confusion.

Does this code cause strong reference cycle?

If not, when will ARC deallocate the instance of Person? the method named deinit in Person class is never called.

Upvotes: 3

Views: 1035

Answers (1)

Puttin
Puttin

Reputation: 1615

Yes, this's a typical retain cycle.

To solve this problem use [weak self] in your closure

person.closure = { [weak self] in
    guard let strongSelf = self else { return }
    print("\(strongSelf.aStr)")
}

To really create a leak.
I create a demo App. Root is a navController.
The navController has a root controller. Let's call it buttonController. When you click button in the buttonController, it create your ViewController and push to navController. When you click back button in navigation bar, the navController pop your ViewController instance.

Profile it, then you will see the leak and the retain cycle in Instruments.

Xcode default template of iOS App use a single page, which always retain your ViewController instance. If the ViewController instance is still used by the system, it's actually not a leak yet. So push & pop show that leak for you.

Upvotes: 2

Related Questions