2017-03-04 76 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

相關問題