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

旧街凉风 提交于 2020-03-20 06:25:50

问题


I have a UIView that am adding to a UIViewController and am generally testing de-initialization to make sure I am doing things right. But when I don't set the variable in my viewController to nil and only use .removeFromSuperView() , the deinit() method in UIView won't be called until I add the UIView another time then its called. But if I use removeFromSuperView() and set the variable to nil then deinit() is called right away. Why is that?

Here's 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")
    }
}

Here's the parent 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

    }


}

回答1:


deinit is called when no one is referencing the object. If you don't set tstview to nil, your MyViewController is still referencing it, thus deinit won't be called. When you call addView, the statement tstview = test finally removes the last reference to the old view, thus triggering the deinitializer.

You can read more about the concept of deinitialization in the Swift documentation.


If you want to be notified as soon as the view is detached, override willMove(toSuperview:) instead.

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


来源:https://stackoverflow.com/questions/42598996/why-is-deinit-not-called-until-uiview-is-added-to-parent-again

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!