class MyClass {
var someProperty = 0
deinit {
// never gets called
}
func doSomething() {
DispatchQueue.global().async { [weak self] in
Thread.sleep(forTimeInterval: 3600)
self?.someProperty = 123
}
}
}
class MyViewController: UIViewController {
var myClass: MyClass?
deinit {
// MyViewController gets properly deallocated
}
override func viewDidLoad() {
super.viewDidLoad()
myClass = MyClass()
myClass?.doSomething()
}
}
运行上述代码时,即使 MyViewController 从导航堆栈弹出或被解除,MyClass 也永远不会被释放。
但是,如果我将 MyClass 的实现直接移动到 MyViewController,一切都会按预期进行:
class MyViewController: UIViewController {
var someProperty = 0
deinit {
// MyViewController still gets properly deallocated
}
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async { [weak self] in
Thread.sleep(forTimeInterval: 3600)
self?.someProperty = 123
}
}
}
我使用 Debug Memory Graph 来找出仍然保留对 MyClass 实例的引用,这就是我得到的:
为什么还有参考?我在这里想念什么?
更新
因此,我试图弄清楚为什么它可以与 MyViewController 一起使用,但在两者之间有另一个实例时却不行。似乎从 NSObject 继承有所不同。当我从 NSObject 继承 MyClass 时,会调用 deinit 并且一旦完成长操作,self 就会正确设置为 nil。
现在的问题是,Swift 中的捕获列表与 NSObject 有什么关系?