I have a subclass of NSView
called MyView
, and I have a nib file whose File's Owner
is MyView
. I would like to create copies of a view in my nib file, and so I am using a class function as shown below:
class MyView: NSView {
@IBOutlet var myImageView: NSImageView! // Cocoa class
@IBOutlet var myEditingField: EditingField! // Custom subclass of cocoa object
class func initWithTitle(_ title: String) -> MyView {
let myNib = NSNib(nibNamed: "MyView", bundle: nil)
var myArray = NSArray()
myNib!.instantiate(withOwner: self, topLevelObjects: &myArray) // instantiate view and put in myArray
var myViewInstance = myArray[0] as! MyView
myViewInstance.imageView.image = NSImage(named: title)
myViewInstance.myEditingField.stringValue = title // this line
return myViewInstance
}
}
I have connected an IBOutlet
from an NSImageView
in the view in my nib file to the property myImageView
in the MyView
class, and I have connected an IBOutlet
from an EditingField
, a custom subclass of NSTextField
that I wrote, to the myEditingField
property. So, to create an instance of MyView
simply I do:
let instance = MyView.initWithTitle("foo")
The issue with this method is that when IB
creates the view, it is calling the required initializer init(coder:)
on the EditingField
in the view in the nib file. Originally, I had left my implementation of init(coder:)
as simply the default fatalError("init(coder:) is not implemented")
because I didn't think IB
would call that initializer. I had figured IB
would call init(frame:)
, but in reality it does call init(coder:)
. So, I tried implementing init(coder:)
the following way:
class EditingField: NSTextField {
var id: String
// ... other properties
required init?(coder: NSCoder) {
print("init coder")
self.id = "default"
// ... other properties get default values, just like id
super.init(coder: coder)
}
}
Unfortunately, this did not work either. When I run the project using the above initializer in EditingField
, the line myViewInstance.myEditingField.stringValue = title
in MyView
throws an error. When this happens, the debugger console reveals that the property myEditingField
is nil, and, unlike myImageView
, hasn't been initialized at all (despite the fact that the print message in init(coder:)
still prints!)
So, my questions are (1) how do I initialize/create an NSView
from a nib file that has custom objects in it? (2) why does IB
call init(coder:)
on EditingField
? and (3) why is myEditingField
nil despite the print message suggesting that the initializer ran?