0

This is a simple class I wanted to have instantiated with two arrays to populate an NSTableView on a mac app:

class TableController: NSObject, NSTableViewDataSource, NSTableViewDelegate {

    var paintingNames:[String]
    var paintingKeys:[String]

    init(names:[String], keys:[String]) {
        paintingNames = names
        paintingKeys = keys
    //      breakpoint here shows both arrays have values
   }
...
}

When I step through the code as it is being initialized, everything works up to this point. Then I get this error:

"fatal error: use of unimplemented initializer 'init()' for class..."

So I can can avoid this error, by adding the arrays optionals (not what I want as they are the tableView's dataSource) and adding an override init() call:

class TableController: NSObject, NSTableViewDataSource, NSTableViewDelegate {

var paintingNames:[String]?
var paintingKeys:[String]?

override init() { // this gets called after the first custom init function

    // a breakpoint here shows the arrays are now both nil
}

init(names:[String], keys:[String]) { //this gets called first
    paintingNames = names
    paintingKeys = keys
    //      breakpoint here shows both arrays have values
}
...
}

Without the nil check on the arrays in the override init() call, the arrays are nil. Even with this bit of logic added:

override init() { // this gets called after the first custom init function
    if paintingNames != nil {
        paintingNames = [String]()
    }

    if paintingKeys != nil {
        paintingKeys = [String]()
    }
} 

they are still nil.

What is going on here?

2
  • 1
    what is the point of the nil check? read it again, does it make any sense? Commented Nov 10, 2014 at 4:52
  • I was grasping at straws with the nil check, that's for sure. Commented Nov 10, 2014 at 18:01

1 Answer 1

4

The reason why making the arrays as optionals works is because optionals are automatically assigned nil.

var paintingNames:[String]?
var paintingKeys:[String]?

does the exact same thing as

var paintingNames:[String]? = nil
var paintingKeys:[String]? = nil

You can actually remove the init() declaration at this point as your default initialiser is already implicitly created for you.

You haven't added any code to show WHERE the default initialiser is being called, I hope you aren't calling two init() functions... that is a recipe for unexpected results.

If you only ever want objects of this class to be instantiated using the init(names:[String], keys:[String]) initialiser, just make your default initialiser throw an exception, i.e.,

init() {
    fatalError("init() has not been implemented")
}

This would prevent you from ever making the mistake of creating an object using init(). Another way would be to just make your init() into:

override convenience init() {
    self.init(names:nil, keys:nil)
}

In case you don't know, convenience initialisers allow you to call other local initialisers from within an initialiser.

Sign up to request clarification or add additional context in comments.

1 Comment

"You haven't added any code to show WHERE the default initialiser is being called, I hope you aren't calling two init() functions... that is a recipe for unexpected results." This was my problem. IB is calling init() as TableController is the delegate/data source for an NSTableView. This is my first mac app and NSTableView has a few more manual setup steps than UITableView!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.