4

我有一个正在添加到 UIViewController 的 UIView,并且通常正在测试反初始化以确保我做对了。但是,当我没有将 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")
    }
}

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

    }


}
4

1 回答 1

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")
        }
    }
}
于 2017-03-04T17:33:08.550 回答