2016-08-03 59 views
0

上下文: 我創建的UIView(爲helloView)的子類顯示一些文本和一個按鈕在我MainViewController視圖的頂部。 這個子類在MainVC viewDidLoad初始化,並添加到視圖:view.addSubview(helloView)self.removeFromSuperview()UIView子類內

目的:爲helloView具有一個UIButton(continueButton)與目標dimissHelloView。此方法只需簡單地調用self.removeFromSuperView()即可輕鬆獲取屏幕上的helloView。

問題:用戶與按鈕的交互會中斷代碼並返回一個零指針異常(意外地發現零,同時展開可選值)。儘管SO和Google搜索有幾個小時,但我無法通過自己的按鈕子視圖找到解除視圖的正確方法。

以前的疑難解答:當調用removeFromSuperview時,看起來superview爲零,但如果我使用斷點並在控制檯中調用它,則不是。

代碼:忽略屬性和約束塊,按鈕創建和目標操作在底部。

import UIKit 

class HelloView: UIView { 

    var helloText: String = "" 
    var continueButton: UIButton! 

    override init(frame: CGRect) { 
     super.init(frame: frame) 

     didLoad() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 

     didLoad() 
    } 

    func didLoad(){ 

     self.translatesAutoresizingMaskIntoConstraints = false 
     setContinueButton() 
     self.addSubview(continueButton) 
    } 

    override func didMoveToSuperview() { 
     setConstraints() 
    } 

    func setConstraints(){ 

     //remove any previous constraints 
     for constraint in superview!.constraints { 
      if constraint.firstItem as! UIView == self && constraint.secondItem as? UIView == superview { 
       superview!.removeConstraint(constraint) 
      } 
     } 

     // Hello View basic constraints 
     let xAxisConstraint = NSLayoutConstraint(item: self, attribute: .CenterX, relatedBy: .Equal, toItem: superview, attribute: .CenterX, multiplier: 1, constant: 0) 
     let yAxisConstraint = NSLayoutConstraint(item: self, attribute: .CenterY, relatedBy: .Equal, toItem: superview, attribute: .CenterY, multiplier: 1, constant: 0) 

     // check device orientation and add constraints consequently 
     if UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation) { 
      let widthConstraint = NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, toItem: superview, attribute: .Width, multiplier: 1, constant: -100) 
      let heightConstraint = NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, toItem: superview, attribute: .Height, multiplier: 1, constant: -150) 
      superview!.addConstraints([xAxisConstraint, yAxisConstraint, widthConstraint, heightConstraint]) 
     } 
     if UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation){ 
      let widthConstraint = NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, toItem: superview, attribute: .Width, multiplier: 1, constant: -100) 
      let heightConstraint = NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, toItem: superview, attribute: .Height, multiplier: 1, constant: -300) 
      superview!.addConstraints([xAxisConstraint, yAxisConstraint, widthConstraint, heightConstraint]) 
     } 

     // Continue Button constraints 
     let centerXConstraint = NSLayoutConstraint(item: continueButton, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1, constant: 0) 
     let bottomConstraint = NSLayoutConstraint(item: continueButton, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1, constant: -8) 
     self.addConstraints([centerXConstraint, bottomConstraint]) 
    } 

    func setContinueButton(){ 
     continueButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 20)) 
     continueButton.setTitle("Continue", forState: .Normal) 
     continueButton.setTitleColor(UIColor.whiteColor(), forState: .Normal) 
     continueButton.addTarget(self, action: #selector(HelloView.dismissHelloView), forControlEvents: .TouchUpInside) 
     continueButton.translatesAutoresizingMaskIntoConstraints = false 
    } 

    func dismissHelloView(){ 
     print(superview!) 
     self.removeFromSuperview() 
    } 

} 

回答

0

當你從它的父刪除一個視圖,didMoveToSuperview是會得到調用(SuperView把會nil)。您的setConstraints函數從didMoveToSuperview調用,並且它的解壓superview,這是零,導致崩潰。可選項的全部點是強制你考慮如果某些事情是零的話會發生什麼。

不管怎樣,在你的情況,你什麼都不想當上海華變成零的情況發生,所以我把這樣的事情在didMoveToSuperview頂部:

guard superview != nil else { return } 
+0

非常感謝@zpasternack,我沒有意識到didMoveToSuperview被調用removeFromSuperview!爲提前回報添加警戒聲明解決了問題。 –