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

The*_*Ben 4 memory memory-leaks swift deinit swift3

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

这是 UIView() 类:

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

这是父 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

    }


}
Run Code Online (Sandbox Code Playgroud)

ken*_*ytm 5

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

您可以在Swift 文档 中阅读有关取消初始化概念的更多信息。


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

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