2014-07-04 12 views
9

Ich möchte ein Fenster-Controller-Objekt aus einer Nib-Datei initialisieren, ganz einfach, oder? Aber ich kann es einfach nicht zur Arbeit bringen.Wie initialisiert man einen NSWindowController in Swift?

Nach meinen bisherigen Erfahrungen in ObjC, habe ich den folgenden Code abgewertet:

init() { 
    super.init(windowNibName: "SplitWindowController") 
} 

Und in der AppDelegate Datei, habe ich einfach init und zeigt das Fenster:

var myWindowController: MyWindowController = MyWindowController() 
myWindowController.showWindow(self) 
myWindowController.window.makeKeyAndOrderFront(nil) 

Aber der Compiler gibt mir diesen Fehler: Must call a designated initializer of the superclass 'NSWindowController'. Und gemäß der Swift-Version von NSWindowController Definition, gibt es nur 3 bezeichnet Initialisierer, nämlich init(), init(window), init(coder). Ich weiß nicht, was ich als nächstes tun soll. Soll ich eine NSCoder aus einer Nib-Datei erstellen, die ich nicht weiß, wie zu tun ist?

+0

@George hier sehen Sie Ihre Frage zu beantworten: [Subclassing NSWindowController] [1] [1]: http: // Stapelüberlauf.com/questions/24220638/subclassing-nswindowcontroller-in-swift-und-initwindownibname – mqueue

Antwort

4

NSWindowController hat 2 bezeichnet initializers:

init(window: NSWindow!) 
init(coder: NSCoder!) 

Wenn eine Unterklasse erstellen, sollten Sie die bestimmten Initialisierung seiner übergeordneten Klasse aufrufen. Aktuelle Versionen von Xcode erzwingen dies. Entweder über eingebauten Sprachmechanismus (Swift) oder über NS_DESIGNATED_INITIALIZER Makro (Objective-C).

Swift erfordert außerdem, dass Sie den benannten Initialisierer der Superklassen aufrufen, wenn Sie einen praktischen Initialisierer überschreiben.
Vom "Initialization: Designated Initializers and Convenience Initializers" Abschnitt Swift Programming Guide:

If the initializer you are overriding is a convenience initializer, your override must call another designated initializer from its own subclass, as per the rules described above in Initializer Chaining.

In Ihrem Fall sollten Sie wahrscheinlich init(window: NSWindow!) außer Kraft setzen und von dort Super Pendant nennen.

+0

Danke für Ihre Erklärung, ich frage mich, wie kann ich ein NSWindow-Objekt aus Nib-Datei erstellen? –

+0

Ich meine das Fensterobjekt sollte aus der Nib-Datei erstellt werden, oder? Und wie kann ich das Fenster aus der Nib-Datei erstellen? –

+0

Wenn Sie einen dedizierten xib für Ihren Fenstercontroller haben, können Sie Ihre Unterklasse im Identity Inspector des Dateieigentümers als "Benutzerdefinierte Klasse" festlegen. Beachten Sie, dass Sie, wenn der Fenstercontroller aus der XIB erstellt wird, initWithCoder anstelle von initWithWindow überschreiben müssen, wenn Sie im Initialisierer etwas Bestimmtes tun möchten. –

5

Sie waren fast da. Sie können in der Tat init() als Bequemlichkeit initialiser in einer Art und Weise außer Kraft setzen, die dem Obj-C-Code entspricht hast du verwendet, um:

import Cocoa 

class MyWindowController: NSWindowController { 

    override convenience init() { 
     self.init(windowNibName: "<xib name>") 
    } 
} 

Beachten Sie, dass init(windowNibName:) auf self anrufen, weil init() eine Bequemlichkeit initialiser zu sein, Sie Erben Sie immer noch alle Initialisierer von der Oberklasse. Von documentation:

Rule 1: A designated initializer must call a designated initializer from its immediate superclass.

Rule 2: A convenience initializer must call another initializer from the same class.

Rule 3: A convenience initializer must ultimately call a designated initializer.

Auch als @weichsel oben erwähnt, stellen Sie sicher, dass Sie die Klasse der File's Owner auf Ihre Unterklasse von NSWindowController gesetzt (in dem obigen Beispiel wäre, dass MyWindowController) und dann seine window verbinden Steckdose mit dem Fenster selbst.

Das ist gesagt, ich bin mir nicht sicher, warum Compiler für die override Schlüsselwort hinzugefügt werden soll. Obwohl NSWindowController ist eine Unterklasse von NSResponder, die eine init() definiert, der folgende Code kompiliert, ohne Frage, auch wenn diese eine gleichwertige Vererbungshierarchie implementiert:

class A { 
    init() { } 
} 

class B: A { 
    init(Int) { 
     super.init() 
    } 
    convenience init(String) { 
     self.init(5) 
    } 
} 

class C: B { 
    convenience init() { 
     self.init("5") 
    } 
} 
+0

Ich bekomme einen "Initialisierer überschreibt einen designierten Initialisierer von seiner Oberklasse" Fehler in Xcode 7.3. Wenn Sie das Schlüsselwort 'override' entfernen, wird der Fehler behoben. –

+1

@NicolasMiari, offensichtlich wurde dieser spezielle Fehler von Apple angesprochen, seit dieser Beitrag geschrieben wurde. Danke, dass du dir das notiert hast! Was sich auch geändert hat, ist, dass wir nun die unbenannten Parameter explizit markieren müssen (statt "init (Int)" schreiben wir jetzt "init (_: Int)". – milos

Verwandte Themen