为什么在 UIView 再次添加到父级之前不调用 deinit?

Why is deinit not called until UIView is added to parent again?

我有一个要添加到 UIViewController 的 UIView,并且通常会测试取消初始化以确保我做的事情是正确的。但是当我没有将 viewController 中的变量设置为 nil 并且只使用 .removeFromSuperView() 时,在我再次添加 UIView 然后调用它之前,不会调用 UIView 中的 deinit() 方法。但是,如果我使用 removeFromSuperView() 并将变量设置为 nil,则会立即调用 deinit()。这是为什么?

这是 UIView() class:

class TestView: UIView {

    override init(frame: CGRect) {
        super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
        print("init is happneing")
    }

    deinit {
        print("de init is happneing")
    }


    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

这是父级 ViewController:

class MyViewController: UIViewController { 
 var tstview  : TestView?


  //adding the UIView by tapping on a button 
 @IBAction func addView(_ sender: UIButton) {

        let test = TestView()
        tstview = test
        tstview?.frame = CGRect(x: 50, y: 60, width: self.view.frame.width-100, height: self.view.frame.height-200)
        tstview?.backgroundColor = UIColor.white
        self.view.addSubview(tstview!)  
}

    override func viewDidLoad() {
       super.viewDidLoad()  
    }

    //removing UIView by touching elsewhere 
   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
         tstview?.removeFromSuperview()
      //  tstview = nil

    }


}

deinit 在没有人引用该对象时调用。如果您没有将 tstview 设置为 nil,您的 MyViewController 仍会引用它,因此不会调用 deinit。当您调用 addView 时,语句 tstview = test 最终删除了对旧视图的最后一个引用,从而触发了析构程序。

您可以在 Swift documentation 中阅读更多关于取消初始化的概念。


如果您想在视图分离后立即收到通知,请改为override willMove(toSuperview:)

class TestView: UIView {
    ...
    override func willMove(toSuperview newSuperview: UIView?) {
        if newSuperview == nil {
            print("removed from parent")
        }
    }
}