I came across something that's peculiar and interesting and would love to get inputs from anyone. So to start off with lets take this definition of the class:
class TestClass:NSObject {
var s1 = NSHashTable<TestClass>(options: .weakMemory)
func doit(bla:TestClass) {
s1.add(bla)
bla.s1.add(self)
}
deinit {
print("Deinit")
}
}
Now lets consider the following:
var t1:TestClass? = TestClass()
var t2:TestClass? = TestClass()
If we did the following deinit gets called:
t1?.s1.add(t2!)
t2?.s1.add(t1!)
t1 = nil // This will result in deinit being called
Now lets do the same thing but by calling doit() method
t1?.doit(bla:t2!)
t1 = nil // Deinit doesn't get called for some reason
The question here is why isn't deinit being called in this situation? What is so different about this since it essentially has the same reference assignment as the first method?
I would love to get input from anyone on this.
As usual, the problem is that you are trying to test this in a playground. Don't. Playgrounds are the work of the devil.
Test in an actual app project and you will see that deinit
is called.
Example (iOS, but the equivalent in macOS would do fine):
import UIKit
class TestClass:NSObject {
var s1 = NSHashTable<TestClass>(options: .weakMemory)
func doit(bla:TestClass) {
s1.add(bla)
bla.s1.add(self)
}
deinit {
print("Deinit")
}
}
class ViewController: UIViewController {
var t1:TestClass? = TestClass()
var t2:TestClass? = TestClass()
override func viewDidLoad() {
super.viewDidLoad()
t1?.doit(bla:t2!)
t1 = nil // --> "Deinit"
print(t2?.s1) // --> it's empty
}
}