Swift: I don't understand why this code hasn't memory leak

This code print "choco’s memory discard" as a result.

But I think this code has memory leak.
Because saveClosure function is pointing let choco’s name from the stack. and Closure run is pointing the name in the heap. so let choco’s refrence counting is 2.

Also var run is pointing savaClosure. So there is storng reference cycle. But the result is activating deinit.

What am I missing?

class Dog {
    var name = "choco"

    var run: (() -> Void)?

    func walk() {
        print("\(self.name) is running.")
    }

    func saveClosure() {

        run = {
            print("\(self.name) is running.")
        }
    }

    deinit {
        print("\(self.name)'s memory discard")
    }
}


func doSomethiing() {
    let choco: Dog? = Dog()
}

doSomething()
//choco's memory discard
class Dog {
    var name = "choco"

    var run: (() -> Void)?

    func walk() {
        print("\(self.name) is running.")
    }

    func saveClosure() {

        run = {
            print("\(self.name) is running.")
        }
    }

    deinit {
        print("\(self.name)'s memory discard")
    }
}


func doSomethiing() {
    let choco: Dog? = Dog()
}

doSomething()
// Memory Leak

>Solution :

There is no memory leak because your code does not call saveClosure(). This means that run remains nil.

If you change doSomething to call saveClosure() then there is a retain cycle, the deinit is not called and there is no message printed:

func doSomething() {
    let choco: Dog? = Dog()
    choco?.saveClosure()
}

By the way, there is no need for choco to be optional as it doesn’t affect the behaviour.

Leave a Reply