2016-08-03 28 views
0

Kontext: Ich habe eine Unterklasse von UIView (helloView) erstellt, um Text und eine Schaltfläche oberhalb meiner MainViewController-Ansicht anzuzeigen. Diese Unterklasse wird in den MainVC initialisiert viewDidLoad und zu der Ansicht: view.addSubview(helloView)self.removeFromSuperview() innerhalb der UIView-Unterklasse

Ziel: helloView hat eine UIButton (continueButton) mit einem Ziel dimissHelloView. Diese Methode ruft einfach self.removeFromSuperView() an, um einfach Fahrt von helloView auf dem Bildschirm zu erhalten.

Problem: eine Benutzerinteraktion mit der Schaltfläche bricht den Code und gibt eine Nullzeigerausnahme zurück (unerwartete Null beim Entpacken eines optionalen Werts). Trotz einiger Stunden bei SO- und Google-Suchen konnte ich nicht den richtigen Ansatz finden, um eine Ansicht über eine eigene Schaltflächenunteransicht zu verwerfen.

Vorherige Fehlerbehebung: Es scheint, dass Superview ist Null, wenn die removeFromSuperview aufgerufen wird, aber es ist nicht, wenn ich einen Haltepunkt verwenden und es in der Konsole aufrufen.

Code: Ignorieren Sie die Attribute und Einschränkungen Stück, die Schaltfläche Erstellung und Zielaktion sind am unteren Rand.

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() 
    } 

} 

Antwort

0

Wenn Sie eine Ansicht aus seiner Superview entfernen, wird didMoveToSuperview genannt werden (die Superview wird nil sein). Ihre setConstraints Funktion wird von didMoveToSuperview aufgerufen, und es ist Force Unwrapping superview, die Null ist, verursacht den Absturz. Der springende Punkt von optionals ist es zwingt Sie zu prüfen, was passiert, wenn etwas null ist.

Wie auch immer, in Ihrem Fall, dass Sie nicht wollen, etwas geschehen, wenn die Super Null wird, so würde ich so etwas wie dies an der Spitze der didMoveToSuperview setzen:

guard superview != nil else { return } 
+0

Vielen Dank @zpasternack, ich DidMoveToSuperview wurde auf removeFromSuperview aufgerufen! Das Hinzufügen der Guard-Anweisung für eine vorzeitige Rückkehr löste das Problem. –

Verwandte Themen