2014-07-04 11 views
9

Desidero inizializzare un oggetto controller di finestra da un file di pennino, abbastanza semplice, vero? Ma semplicemente non riesco a farlo funzionare.Come inizializzare un NSWindowController in Swift?

Secondo la mia esperienza precedente in objC, ho scritto verso il basso il seguente codice:

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

E nel file app delegato, ho semplicemente init e visualizza la finestra:

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

Ma il compilatore mi dà questo errore: Must call a designated initializer of the superclass 'NSWindowController'. E secondo la versione Swift della definizione NSWindowController, ci sono solo 3 designati inizializzatori, ovvero init(), init(window), init(coder). Non so cosa fare dopo. Devo costruire un NSCoder da un file pennino, che non so come fare?

+0

@George vedere qui per rispondere alla tua domanda: [Subclassing NSWindowController] [1] [1]: http: // stackoverflow.it/questions/24220638/subclassing-nswindowcontroller-in-swift-and-initwindownibname – mqueue

risposta

4

NSWindowController ha 2 inizializzatori designati:

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

Durante la creazione di una sottoclasse, si dovrebbe invocare l'inizializzatore designato della sua superclasse. Le versioni recenti di Xcode fanno rispettare questo. O tramite meccanismo di linguaggio incorporato (Swift) o tramite la macro NS_DESIGNATED_INITIALIZER (Objective-C).

Inoltre, Swift richiede di chiamare l'inizializzatore delle superclassi quando si sostituisce un inizializzatore di convenienza.
Dalla sezione "Initialization: Designated Initializers and Convenience Initializers" della Guida Swift programmazione:

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.

Nel tuo caso, probabilmente si dovrebbe ignorare init(window: NSWindow!) e chiamare omologo di super-da lì.

+0

Grazie per la tua spiegazione, mi chiedo come posso costruire un oggetto NSWindow dal file pennino? –

+0

Voglio dire che l'oggetto finestra dovrebbe essere costruito dal file pennino, giusto? E come posso costruire la finestra dal file del pennino? –

+0

Se si dispone di uno xib dedicato per il controller della finestra, è possibile impostare la sottoclasse come "Classe personalizzata" nell'Ispettore identità del proprietario del file. Si noti che quando il controller della finestra viene creato dallo xib, è necessario eseguire l'override di initWithCoder anziché initWithWindow se si desidera eseguire un'operazione specifica nell'inizializzatore. –

5

Eri quasi arrivato. È infatti possibile ignorare init() come initialiser convenienza in un modo che è equivalente al codice Obj-C vi siamo abituati:

import Cocoa 

class MyWindowController: NSWindowController { 

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

noti che si sta chiamando init(windowNibName:) su self, perché init() essere un initialiser comodità, è eredita ancora tutti gli inizializzatori dalla superclasse. Da 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.

Inoltre, come accennato in precedenza @weichsel, assicurarsi di impostare la classe del File's Owner alla vostra sottoclasse di NSWindowController (nell'esempio di cui sopra, che sarebbe MyWindowController) e quindi collegare il suo window presa con la finestra stessa.

Detto questo, non sono sicuro del perché il compilatore chiede la parola chiave override da aggiungere. Anche se NSWindowController è una sottoclasse di NSResponder, che definisce un init(), il seguente codice compilato senza alcun problema anche se si implementa una gerarchia di ereditarietà equivalente:

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

Ricevo un errore "Inizializzatore non sovrascrive un inizializzatore designato dalla sua superclasse" in Xcode 7.3. La rimozione della parola chiave 'override' elimina l'errore. –

+1

@NicolasMiari, ovviamente, quel particolare bug è stato risolto da Apple da quando questo post è stato scritto. Grazie per aver preso nota di ciò! Ciò che è cambiato è che ora dobbiamo contrassegnare esplicitamente i parametri senza nome (invece di 'init (Int)', ora scriviamo 'init (_: Int)'. – milos

Problemi correlati