Swift: Benutzerdefinierte ViewController-Initialisierer

87

Wie fügen Sie UIViewControllerUnterklassen in Swift benutzerdefinierte Initialisierer hinzu ?

Ich habe eine Unterklasse erstellt UIViewController, die ungefähr so ​​aussieht:

class MyViewController : UIViewController
{
    init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
    {
        self.leftVC = leftVC;
        self.rightVC = rightVC;
        self.gap = gap;

        super.init();

        setupScrollView();
        setupViewControllers();
    }
}

Wenn ich es ausführe, wird ein schwerwiegender Fehler angezeigt:

Schwerwiegender Fehler: Verwendung des nicht implementierten Initialisierers 'init (nibName: bundle :)' für die Klasse 'MyApp.MyViewController'

Ich habe an anderer Stelle gelesen, dass man beim Hinzufügen eines benutzerdefinierten Initialisierers auch überschreiben muss. init(coder aDecoder:NSCoder)Lassen Sie uns das überschreiben initund sehen, was passiert:

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

Wenn ich das hinzufüge, beschwert sich Xcode darüber self.leftVC is not initialized at super.init call. Ich denke, das kann auch nicht die Lösung sein. Ich frage mich also, wie ich einer ViewControllerUnterklasse in Swift benutzerdefinierte Initialisierer ordnungsgemäß hinzufügen kann (da dies in Objective-C kein Problem zu sein scheint).

BadmintonCat
quelle
Wie versuchst du deine zu instanziieren MyViewController?
Mike Pollard
Warum nicht alles in viewDidLoad () instanziieren, dort können Sie sie genau so initialisieren, wie Sie möchten
tudoricc
@MikePollard mit dualViewCtrl = DualViewCtrl (leftVC: l, rightVC: r, gap: 50) ... Ich habe bereits herausgefunden, dass ich den initWithNib-Initialisierer verwenden muss.
BadmintonCat
3
@tudoricc Weil Sie häufig Instanzeigenschaften wünschen, die im Initialisierer mit bestimmten Parametern sicher initialisiert werden. In viewDidLoad ist dies nicht möglich, da nicht garantiert werden kann, dass die Eigenschaften bei Bedarf verfügbar sind.
BadmintonCat
Es tut mir leid, dass ich in meinem Kopf viewDidLoad () als Initialisierer sehe. Danke für die Erklärung
Tudoricc

Antworten:

121

Ich habe es gelöst! Man muss den angegebenen Initialisierer aufrufen, der in diesem Fall der Init mit nibName ist, offensichtlich ...

init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
{
    self.leftVC = leftVC
    self.rightVC = rightVC
    self.gap = gap

    super.init(nibName: nil, bundle: nil)

    setupScrollView()
    setupViewControllers()
}
BadmintonCat
quelle
31
Werde
8
Ich mag Semikolons. Sie machen Code weniger mehrdeutig, insbesondere bei den lächerlich ausführlichen Namen und Signaturen der Cocoa / Cocoa-Touch-API. Schlechte Entscheidung der Swift-Designer, sie IMHO zu entfernen.
BadmintonCat
25
IMHO, wenn Sie ein Zeichen
eingeben
31
@SamSoffes, damit Sie überhaupt kein (zusätzliches) Leerzeichen verwenden? Und Sie verschleiern alle Symbole als einzelne Zeichen?
Victor Jalencas
7
Diese Diskussion erinnert mich an Tabs vs Leerzeichen im Silicon Valley
Aaron
13

Für einen allgemeineren UIViewController können Sie diesen ab Swift 2.0 verwenden

init() {
    super.init(nibName: nil, bundle: nil)
}
Tr0yJ
quelle
11

Sie sind sich nicht sicher, ob Sie es geschafft haben, dieses Problem vollständig zu lösen. Abhängig davon, wie die Benutzeroberfläche Ihrer Klasse aussehen soll und ob Sie die Codiererfunktionalität tatsächlich benötigen oder nicht, können Sie auch Folgendes verwenden:

convenience required init(coder aDecoder: NSCoder)
{
    //set some defaults for leftVC, rightVC, and gap
    self.init(leftVC, rightVC, gap)
}

Da init:leftVC:rightVC:gapes sich um einen festgelegten Initialisierer handelt, können Sie die Implementierungsanforderung erfüllen, init:coderindem Sie ihn zu einem praktischen Initialisierer machen, der Ihren festgelegten Initialisierer aufruft.

Das könnte besser sein als

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

Wenn Sie einige Eigenschaften initialisieren müssen, müssen Sie sie neu schreiben.

wlingke
quelle
8

Swift 5

Wenn Sie einen benutzerdefinierten Initialisierer schreiben möchten, mit UIViewControllerdem initialisiert wirdstoryBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")

Sie können einen benutzerdefinierten Initialisierer nur für OptionalEigenschaften schreiben .

class MyFooClass: UIViewController {
    var foo: Foo?

    init(with foo: Foo) {
        self.foo = foo
        super.init(nibName: nil, bundle: nil)
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.foo = nil
    }
}
emrcftci
quelle