2017-07-06 5 views
2

Ich habe ein gutes Stück Suche hier und auf YouTube gemacht, aber mein Problem nicht anderswo repliziert gesehen. Ich werde es auf den Punkt bringen.Swift Delegation: unerwartet gefunden Null beim Entpacken ein optionaler Wert

Ich habe 2 View-Controller, die ich selbst codiert habe - nicht von XCode generiert-; TabOneController und TabTwoController

unten ist die Codierung für beide ...

import UIKit 

class TabOneController: UIViewController{ 


    private let instanceOfTabOneView = TabOneView() 

    var vc1Delegate: fromOneToTwo! 

    override func loadView() { 

     super.loadView() 

      view.addSubview(instanceOfTabOneView.buildTheVu()) 
       view.backgroundColor = UIColor.white 

     runThisOnce() 

     } 

    func runThisOnce(){ 

     vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController") 

    } 

} 

protocol fromOneToTwo{ 

    func passTheValue(heroNameIs: String) 

} 

wie für Reiter 2 ...

import UIKit 

class TabTwoController: UIViewController, fromOneToTwo{ 


    private let instanceOfTabTwoView = TabTwoView() 


    override func loadView() { 

     super.loadView() 

      view.addSubview(instanceOfTabTwoView.buildTheVu()) 

     assignDelegateToSelf() 

    } 

    func assignDelegateToSelf(){ 

     let instanceTabOne = TabOneController() 
      instanceTabOne.vc1Delegate = self 

    } 

    func passTheValue(heroNameIs:String){ 

     instanceOfTabTwoView.txtFld.text = heroNameIs 

    } 

} 

Ich erhalte die folgende Fehlermeldung zur Laufzeit -das App baut erfolgreich- ...

fatal error: unexpectedly found nil while unwrapping an Optional value

auf der folo Flügel Linie ...

vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController") 

Wenn ich die obige Zeile aus kommentieren, die App baut und betreibt erfolgreich, aber natürlich die App nicht die Delegation auszuführen.

ich irgendwie verstehen, was der Compiler, mir zu sagen versucht, dass die

vc1Delegate 

-I guess- instanziiert worden ist. Aber ich habe unter jedem Stein gesucht und finde nicht, wie ich das umgehen kann.

Ich würde jede Hilfe oder Anleitung schätzen. Sorry, wenn mein Code unreif erscheint, bin ich neu in Swift und programmiere generell. Vielen Dank.

Antwort

1

In einer UITabBarController wird die erste Registerkarte standardmäßig instanziiert. Die View-Controller-Initialisierung führt die loadView aus und findet eine nil, weil die zweite Registerkarte noch nicht initialisiert wurde; Das ist normales Verhalten. Mein Vorschlag besteht darin, den Delegierten mit dem Suffix ? schwach zu machen und den Delegate-Code anderswo auszuführen. Geben Sie außerdem immer den ersten Buchstaben in Klassen- und Protokollnamen ein.

Wenn diese Struktur obligatorisch ist, versuchen Sie stattdessen mit einem benutzerdefinierten Benachrichtigungsbeobachter.

+0

Schätzen Sie Ihre Antwort. Ich werde ein Xcode-Projekt mit zwei regulären Viewcontrollern erstellen und alle UI-Steuerelemente durch Variablen ersetzen. Ich werde einen weiteren Kommentar posten, wenn UITabController das Problem war. Vielen Dank für Ihre Zeit. –

1

Als erstes, Ihr Fehler passiert in Zeile var vc1Delegate: fromOneToTwo!, während Sie diese Delegate-Variable als nicht null deklariert, aber dann passTheValue darauf aufrufen. Eine korrekte Übung ist

var vc1Delegate: fromOneToTwo? 

func runThisOnce(){ 
    if let delegate = vc1Delegate { 
     vc1Delegate.passTheValue(heroNameIs: "pass this to TabTwoController") 
    } 
} 

Zweitens verwenden Sie Delegat nicht korrekt. In der assignDelegateToSelf()-Funktion erstellen Sie eine neue Instanz von TabOneController und dann delegieren zuweisen. Stattdessen müssen Sie die vorhandene TabOneController-Instanz ermitteln und den Delegaten zuweisen.

+0

Wie findet man die vorhandene 'TabOneController' Instanz? – Sebastian

+0

@Sebastian Das hängt davon ab, wie dein Code geschrieben ist ...Wenn Sie Anrufe delegieren möchten, müssen Sie den Delegaten für einen Controller registrieren, und dann können Sie nur Delegatanrufe von diesem Controller empfangen. Wenn Sie Storyboard und normalen Übergang zu neuen Ansichtscontrollern verwenden, müssen Sie sich normalerweise nicht darum kümmern, da Sie nur eine Instanz des Ansichtscontrollers haben. Wenn Sie jedoch den Ansichts-Controller programmgesteuert erstellen (wie das Aufrufen von der Storyboard-Funktion initialisiert), müssen Sie nur einmal initiieren und diesen Instant speichern, damit Sie ihn später wiederfinden und Anrufe empfangen können. –

+0

danke für die Erklärung. Ich war in der Lage, dies zu tun, indem ich die aktuelle Viewcontroller-Klasse in einer Variablen speicherte, als das Segment ausgelöst wurde, und diese Variable dann während des Segments an den anderen View-Controller weitergab – Sebastian

Verwandte Themen