0
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 有什么关系?

4

0 回答 0