Your problem is a thorny one.
- If you create a designated initializer in MainWindowController, as you have done by defining init(), then inside the designated initializer you have to call NSWindowController’s designated initializer:
But NSWindowController’s designated initializer requires that you call it with an argument that is an NSWindow–and you would like to avoid having to construct an NSWindow by hand with code; instead you want to use the window in the .xib file.
- What you would like to do to create the window is call NSWindowController’s convenience initializer, which takes a String argument that is the name of the .xib file:
But as noted above, MainWindowController’s designated initializer cannot call a convenience initializer in the super class, and likewise you can’t define a convenience initializer in MainWindowController that calls a convenience initializer in the super class because a convenience initializer has to call another initializer in the same class.
So it appears that convenience initializers aren’t so convenient after all because you can’t call them from a subclass’s initializers.
[quote]The super.init() line in the first initializer generates the following errors / comments:
[quote]Must call a designated initializer of the superclass 'NSWindowController’
Convenience initializer is declared here[/quote][/quote]
If you check the NSWindowController docs, the designated initializer is:
And inside MainWindowController’s designated initializer:
init() {
self.newVar = "newVar"
super.init()
fatalError("init() has not been implemented")
}
…you never called:
Solutions for how to to subclass NSWindowController are described here:
stackoverflow.com/questions/2422 … downibname
The following works for me in Xcode 6.3.2:
[code]class MainWindowController: NSWindowController {
...
...
/*
//Causes errors:
override init()
{
newVar = "Hello"
super.init()
}
*/
override init(window: NSWindow?)
{
newVar = "World"
super.init(window: window)
}
required init?(coder: NSCoder)
{
newVar = "Goodbye"
super.init(coder: coder)
}
}[/code]
Apparently, if you override all the super class’s designated initializers, then your class will inherit all the superclass’s convenience initializers, so you can create an instance of MainWindowController like this:
That uses NSWindowController’s convenience initializer which takes the .xib file name as an argument. That code ends up setting newVar to “World” because NSWindowController’s convenience init calls NSWindowController’s designated initializer, which takes an NSWindow as an argument, and that designated initializer has been overridden in MainWindowController, so the version in MainWindowController is called. Note that NSWindowController’s convenience initializer takes the .xib file name passed as an argument and creates an NSWindow somehow, then calls NSWindowController’s designated initializer using the newly created NSWindow as the argument.
I would guess that all the trouble you are having is the reason the book never had us create our own initializer in MainWindowController.
Because NSWindowController adopts the NSCoding protocol, NSWindowController apparently inherits a designated initializer from the protocol. I have no idea what the question mark means after “init”, and I had no luck finding any mention of that syntax. Well, if I get rid of the ? after “init”, Xcode tells me that the call to super.init(coder: coder) is “fallible”, and the suggested fix is to add the ? after “init”. I guess that indicates that the method:
might not return a valid instance. I wonder why NSCoding doesn’t specify its init() with a question mark in the docs to indicate that it is fallible?
Here is a good explanation of fallible initializers:
developer.apple.com/swift/blog/?id=17