web-dev-qa-db-de.com

IBOutlet ist null, aber es ist im Storyboard Swift verbunden

Verwendung von Swift 1.1 und Xcode 6.2.

Ich habe ein UIStoryboard, das eine einzelne, benutzerdefinierte UIViewController-Unterklasse enthält. Darauf habe ich eine @IBOutlet-Verbindung vom Typ UIView von diesem Controller zu einer UIViewsubclass auf dem Storyboard. Ich habe auch ähnliche Verkaufsstellen für Unteransichten dieser Ansicht. Siehe Abbildung A.

Zur Laufzeit sind diese Eigenschaften jedoch gleich Null (Abbildung B). Obwohl ich versichert habe, dass ich die Outlets im Interface Builder angeschlossen habe.

Gedanken :

  • Ist es möglich, dass durch die Verwendung einer Unterklasse einer Unterklasse die Initialisierung etwas durcheinander bringt? Ich überschreibe keine Initialisierer
  • awakeFromNib: wird aus irgendeinem Grund nicht angerufen
  • Möglicherweise wird keine Verbindung zu Unteransichten in Unteransichten hergestellt

Dinge, die ich ausprobiert habe:

  • Passende @IBOutlet- und Storyboard-Elementtypen genau (anstelle von UIView)
  • Eigentum und Outlet löschen und wieder hinzugefügt

Figure A

Abbildung A *

Figure B

Abbildung B

* Der verdeckte Code in Figure A lautet:

@IBOutlet private var annotationOptionsView: UIView!
@IBOutlet private var arrivingLeavingSwitch: UISegmentedControl!

Vielen Dank.

86

Das Storyboard erkannte keine weiteren UI-Dinge, die ich hinzugefügt habe. Zur Laufzeit waren alle Referenzen gleich Null. Also löschte ich meinen abgeleiteten Datenordner und dann funktionierten diese Verbindungen wieder.

14

Normalerweise geschieht dies, weil der View Controller seine View-Hierarchie noch nicht geladen hat. Ein Ansichtscontroller lädt seine Ansichtshierarchie nur, wenn etwas die view-Nachricht sendet. Das System tut dies, wenn es Zeit ist, die Ansichtshierarchie tatsächlich auf dem Bildschirm anzuzeigen. Dies geschieht, nachdem Dinge wie prepareForSegue:sender: und viewWillAppear: zurückgegeben wurden.

Da Ihr VC seine Ansichtshierarchie noch nicht geladen hat, sind Ihre Ausgänge noch null.

Sie können die VC zwingen, ihre Ansichtshierarchie zu laden, indem Sie _ = self.view sagen.

125
rob mayoff

Haben Sie versucht, Product> Clean auszuführen. Ich habe ein sehr ähnliches Problem gelöst.

25
ThottChief

Haben Sie Ihren View-Controller von einem Storyboard oder einer NIB aus instanziiert, oder haben Sie ihn direkt über einen Initialisierer instanziiert?

Wenn Sie Ihre Klasse direkt mit dem Initialisierer instanziiert haben, werden die Outlets nicht verbunden. Interface Builder erstellt angepasste Instanzen Ihrer Klassen und kodiert diese Instanzen zur wiederholten Dekodierung in NIBs und Storyboards. Die Klassen selbst werden nicht definiert. Wenn dies Ihr Problem war, müssen Sie lediglich den Code ändern, in dem Sie Ihren Controller erstellen, und nicht die Methoden auf UIStoryboard oder UINib verwenden.

19
Jon Hess

In meinem Fall passierte es, weil ich die loadView-Methode in meiner ViewController-Unterklasse überschreibe, aber vergessen habe, [super loadView] hinzuzufügen.

-(void)loadView {
// blank
}

Wenn Sie die loadView-Methode überschreiben, liegt es in Ihrer Verantwortung, Ihre Unteransichten zu initiieren. Da Sie es überschreiben, haben die Ansichten des Interface Builder keine Möglichkeit, in Kakao-Objekte zu konvertieren, und die Auslässe bleiben somit gleich Null.

Wenn Sie loadView in Ihrer View Controller-Unterklasse implementieren, müssen Sie die Benutzeroberflächenelemente aus Storyboard/Xib in den Code laden.

Oder einfach anrufen

[super loadView];

Damit die Superklasse die Möglichkeit hat, Storyboard/Xib in Code zu laden.

10
zinnuree

Dies geschah mit meiner benutzerdefinierten Ansichtszelle für Sammlungen. Es stellte sich heraus, dass ich meine registerClassforReuseIdentifier-Methode durch registerNib ersetzen musste. Das hat es für mich behoben.

8
rounak

Sie können controller.view aufrufen, um das Laden der Ansicht zu erzwingen, um die IBOutlets zu initialisieren. Anschließend können Sie die Werte zuweisen.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "identifier") {
        let controller = segue.destinationViewController as! YourController
        let _ = controller.view //force to load the view to initialize the IBOutlets

        controller.your_IBOutlet_property = xxx
        ...
        controller.delegate = self
    }
}
6
zsong

Dies geschah für mich, als ich versehentlich die Klasse meines View-Controllers als deklarierte

class XYZViewController: UINavigationController {
}

(dh als UINavigationController nicht als UIViewController).

Xcode greift diesen Fehler nicht auf, die Klasse scheint gut zu bauen, und Funktionen wie viewDidLoad, viewWillAppear usw. werden überschrieben. Aber keine der IBOutlets wird verbunden.

Änderung der Deklaration in

class XYZViewController: UIViewController {
}

reparierte es komplett.

6
HughHughTeotl

Dies geschah für mich, weil ich meinen View Controller versehentlich direkt instanziierte, anstatt ihn durch das Storyboard zu instanziieren. Wenn Sie direkt über MyViewController() instanziieren, werden die Ausgänge nicht verbunden.

5
Eric Conner

Ich stoße dieses Problem kürzlich an! Hier ist mein Gedanke ... Das Problem betrifft weder Ihr Storyboard noch irgendein Link-Problem. Es geht darum, wie Sie Ihren ViewController initiieren. Besonders wenn Sie Swift verwenden. (Beim Erstellen einer Klassendatei ist im Editor kaum etwas zu sehen.) 

Indem Sie einfach die init() aus der Superklasse verwenden, können Sie nichts initiieren, was Sie mit Storyboard gearbeitet haben. Sie müssen also die Initialisierung des ViewControllers ändern. Ersetzen Sie let XXViewController = XXViewController() Durch let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController____. Dadurch wird das Programm aufgefordert, zum Storyboard XXViewController zu suchen und alle IBOutlet in Ihrem Storyboard zu initiieren.

Hoffe, diese Hilfe ~ GL

4
user3882355

Für Swift 3.

func configureView() {
    let _  = self.view
}
3
prog_24

100% Arbeitslösung zum Erstellen von ViewControllern aus XIB ohne StoryBoards

  1. Erstellen Sie die Klasse CustomViewController: UIViewController
  2. Erstellen Sie die Ansicht CustomViewControllerView.xib
  3. Wählen Sie in CustomViewControllerView.xib im Interface Builder Platzhalter -> Eigentümer der Datei
  4. Setzen Sie in "Attributes inspector" Klasse auf CustomViewController
  5. Verbinden Sie im "Connections-Inspektor" die Ansicht "Ansicht" mit der Ansicht von xib auf der obersten Ebene (stellen Sie sicher, dass die Klasse der obersten Ebene nicht auf CustomViewController verweist).
  6. Verbinden Sie im "Connections Inspector" andere Ausgänge (falls erforderlich/vorhanden)
  7. Erstellen Sie eine Instanz von CustomViewController im übergeordneten Ansichtscontroller/App-Delegaten

7.1.

// creating instance
let controller = CustomViewController()

7.2.

// connecting view/xib with controller instance
let bundle = Bundle(for: type(of: controller))
bundle.loadNibNamed("CustomViewControllerView", owner: controller, options: nil)

7.3.

// get/set outlets
controller.labelOutlet.text = "title"
controller.imageOutlet.image = UIImage(named: "image1")
1
Roman M

Für mich hatte derselbe Fehler in einem lokalisierten Storyboard, ein Element wurde in einem Gebietsschema und nicht in dem anderen hinzugefügt. Daher hatte ich einen Nullbezug für dieses Element, wenn auf das fehlende Elementschema umgestellt wurde. Ich musste (redundante) Lokalisierung für entfernen das Storyboard mit https://stackoverflow.com/a/42256341/1356559 .

1
Amr Lotfy

Noch ein Fall, auf den ich gerade gestoßen bin. Ich habe den Namen meiner Klasse für den UIViewController geändert, aber ich habe vergessen, den Namen der .xib-Datei zu ändern, in der die Schnittstelle erstellt wurde. 

Nachdem ich dies gefangen hatte und die Dateinamen den Klassennamen widerspiegelten, war alles gut!

Ich hoffe das hilft jemandem.

1
Brian Trzupek

Sie müssen zuerst die Ansichtshierarchie laden, um die Auslässe im Storyboard zu instanziieren. Dazu können Sie die Methoden loadView oder loadViewIfNeeded manuell aufrufen.

1
maven25

Anderer Fall:

Ihre Ausgänge werden erst eingestellt, wenn die Ansicht des View-Controllers tatsächlich instanziiert ist. Dies geschieht in Ihrem Fall wahrscheinlich kurz nach initWithNibName: bundle: - an welchem ​​Punkt sind sie noch null. Bei allen von Ihnen vorgenommenen Einstellungen müssen diese Ausgänge in der -viewDidLoad-Methode Ihres View-Controllers ausgeführt werden.

1

Überprüfen Sie Ihre IBOutlet-Verbindung, ob sie mit dem Dateieigner oder der Ansicht verbunden war.

1
Ahd Radwan

Wenn Sie view controller programmgesteuert instantiieren. Versuchen Sie dann, es wie unten beschrieben zu erstellen

let initialVC = self.storyboard?.instantiateViewController(withIdentifier: "InitialVC") as! InitialVC

anstatt direkt

let initialVC = InitialVC()

Das hat bei mir funktioniert.

1
Vinoth Vino

Für mich stürzte das ab, weil containerView gleich Null war. 

Hier ist mein Code mit Crash .

@IBOutlet private var containerView: UIView!  // Connected to Storyboard
override open func loadView() {
    containerView.addSubview(anotherView)
}

Das Fehlende war der Aufruf der super.loadView(). Also das Problem gelöst für mich.

Fixcode :

@IBOutlet private var containerView: UIView!
override open func loadView() {
    super.loadView()
    containerView.addSubview(anotherView)
}
1
BLC

Habe noch einen ...

Wenn Sie eine benutzerdefinierte Klasse für eine UITableViewCell haben, vergessen Sie jedoch nicht, Custom im Style der Zelle anzugeben.

1
Phantom59

Sie können überprüfen, ob die Ansicht geladen ist.

if isViewLoaded && view.window != nil {
 //self.annotationOptionsView.
}
1
A. Trejo
  1. wählen Sie die Controller-Dateien .h und .m aus
  2. entfernen Sie den Verweis auf diese Dateien
  3. fügen Sie die Dateien erneut zu Ihrem Projektbaum hinzu
  4. Öffne das Storyboard und baue das Projekt schließlich neu auf
0

Ich hatte das gleiche Problem nach dem Kopieren einer Klasse (verknüpft mit einem Xib), um sie mit einer anderen Viewcontroller-Klasse (verknüpft mit einem Storyboard) wiederzuverwenden

override var nibName

und

override var nibBundle

methoden.

Nachdem ich sie entfernt hatte, begannen meine Verkaufsstellen zu arbeiten.

0
smukamuka

Prüfen Sie, ob Steckdosen fehlen oder nicht.

 enter image description here

Aus Versehen Ich habe meinen View Controller mit AVPlayerViewController anstelle von UIViewController subclassed. Durch die Wiedergabe auf UIViewController Dinge wieder normal. Das sollte helfen.

Keine Build-Bereinigung (normal und vollständig), das Entfernen abgeleiteter Datenordner und das Beenden von Xcode hat für mich funktioniert.

0
Hemang

Ich sehe, du verwendest ViewController !? In ViewController class müssen Sie müssen-viewDidLoad, not-awakeFromNib, -awakeFromNib für UIView-Klasse verwenden

0
EvGeniy Ilyin

In meinem Fall stürzte die App plötzlich ab. Das Debuggen ergab, dass alle Outlets zum Zeitpunkt von viewDidLoad() noch nil waren.

Meine App verwendet immer noch nibs (keine Storyboards) für die meisten Ansichtscontroller. Alles war vorhanden, alle Steckdosen ordnungsgemäß verkabelt. Ich habe es überprüft.

Normalerweise instanziieren wir unsere View-Controller als

let newVC = MYCustomViewController()

... was aus irgendeinem Grund zu funktionieren scheint, solange die .xib genauso benannt wird wie die View Controller-Klasse (nicht sicher, wie das funktioniert. Wir sind not, rufen init(nibName:bundle:) mit nil Argumenten auf oder überschreiben init() Um dies bei self zu tun, wie es normalerweise empfohlen wird ...).

Also habe ich versucht, explizit anzurufen

 let newVC = MYCustomViewController(nibName: "MYCustomViewController", bundle: .main)

... nur mit dem Laufzeitausnahmefehler begrüßt werden: 

*** Beenden der App aufgrund der nicht erfassten Ausnahme 'NSInternalInconsistencyException', Grund: 'NIB konnte nicht im Bundle geladen werden:' NSBundle </ Benutzer/nicolasmiari/Library/Entwickler/CoreSimulator/Devices/3DA3CF21-10D-498F-968-C4FC9E3C1A8D/data /Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app> (geladen) 'mit dem Namen' MYCustomViewController ''

Und dann, ich habe es gesehen:

Das Kontrollkästchen "Zielmitgliedschaft" der .xib-Datei wurde deaktiviert.


Muss passiert sein, wenn Sie einen der häufigen Zusammenführungskonflikte in Bezug auf die Xcode-Projektdatei lösen.

Apple definitiv muss mit einem Projektdateiformat aufwarten, das SCM-freundlicher ist.

0
Nicolas Miari

Ich hatte ein ähnliches Problem, als ich zuvor register (_: forCellReuseIdentifier :) für die benutzerdefinierte Zelle hinzugefügt hatte, nachdem ich die Kennung bereits im Storyboard definiert hatte. Hatte diesen Code in der Funktion viewDidLoad (). Sobald ich es entfernte, funktionierte es gut.

0
Gthoma2

Wenn Sie zwei main.storyboards haben und Änderungen am falschen vornehmen, kann dies passieren. Dies kann passieren, wenn Sie eine Steckdose von einem nicht belegten storyboard anschließen. 

0
ScottyBlades