2017-03-04 51 views
0

我有一个UIView添加到一个UIViewController,我通常测试去初始化,以确保我做正确的事情。但是当我没有在我的viewController中将变量设置为nil并且只使用.removeFromSuperView()时,UIView中的deinit()方法将不会被调用,直到我再次添加UIView然后调用它。但是,如果我使用removeFromSuperView()并将该变量设置为零,则会立即调用deinit()。这是为什么?为什么在UIView再次添加到父级之前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") 
    } 
} 

这里的父视图控制器:

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 

    } 


} 

回答

0

deinit当没有人引用对象被调用。如果你没有设置tstviewnil,你的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") 
     } 
    } 
} 
+0

感谢您的回复,我想确保我不会留下任何泄漏,在这种情况下,据我所知willMove toSuperview将无济于事。我试图理解为什么removeFromSuperview()不会退出,直到我将UIView()的另一个实例添加到我的父控制器,因为那时只有我看到deinit被调用。我查看了文档,但找不到原因。 – TheeBen

+0

@TheeBen请检查更新后的第一段。 – kennytm

+0

不错!现在我懂了!我会尽快接受 – TheeBen

相关问题