mfaani
mfaani

Reputation: 36257

Why doesn't my instance get deallocated?

I have a Person class as below:

class Person{
    var name: String?

    init(name: String){
        self.name = name
    }
    func doWithDelay(){
        let when = DispatchTime.now() + 2
        DispatchQueue.main.asyncAfter(deadline: when) { [weak self] in
            self?.name = "delayed"

            print(self?.name )
        }
    }
    deinit {
        print("Person class is deinited \(self)")
    }
}

I create an instance of Person in the viewController below:

class ViewController: UIViewController {
    var p1 :Person? = Person(name: "MMM")

    override func viewDidLoad() {
        super.viewDidLoad()

        var persons : [Person] = []

        p1!.doWithDelay()

        persons.append(p1!)


        var p3 = Person(name: "OOO") // AAA

        persons.removeAll()

    }

}

If I have var p3 = Person(name: "OOO") then my p1 instance will get deallocated, however if I comment out line AAA or simply replace it with var p3 = "howareyou" then my instance Person instance won't get deallocated at all.

Why?!

Upvotes: 0

Views: 659

Answers (1)

matt
matt

Reputation: 534895

The problem is that you cannot tell one person from another. Rewrite your Person class like this:

class Person: NSObject{
    var name: String?

    init(name: String){
        self.name = name
        super.init()
        NSLog("%@", "Person class is inited \(self)")
    }
    func doWithDelay(){
        let when = DispatchTime.now() + 2
        DispatchQueue.main.asyncAfter(deadline: when) { [weak self] in
            self?.name = "delayed"

            print(self?.name )
        }
    }
    deinit {
        NSLog("%@", "Person class is deinited \(self)")
    }
}

The difference here is (1) we log during init as well as dealloc, and (2) we derive from NSObject because it gives us a unique identifier for self, namely its memory address. We then get:

Person class is inited
<MyApp.Person: 0x618000047470> 
Person class is inited 
<MyApp.Person: 0x61000004b040> 
Person class is deinited 
<MyApp.Person: 0x61000004b040>

And that is exactly what we expect to see: the instance property Person persists, but the local variable Property is created and immediately destroyed again. Local variables are automatic: they are deallocated as soon as we reach the end of their scope (the containing curly braces), and so an object referred to by a local variable vanishes unless you have arranged for a longer-lived reference to retain it.

Upvotes: 2

Related Questions