NSTableView Cell with Identifier keep giving nil
Asked Answered
U

2

5

I am working on building MacOS app. I am trying to make table view that updates the cell when I press add button.

enter image description here

Following is my code:

 func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    let identifier = tableColumn?.identifier as NSString?
    if ( identifier == "NameCell")
    {
        var result: NSTableCellView
        let cell = tableView.make(withIdentifier: "NameCell", owner: self) as! NSTableCellView
        cell.textField?.stringValue = self.data[row].setting!
            return cell

    }
    else if (identifier == "SettingCell")
    {
        if let cell = tableView.make(withIdentifier: "SettingCell", owner: self) as? NSTableCellView {
        cell.textField?.stringValue = self.data[row].setting!
        return cell
    }
    }
    return nil
}

However, the line let cell = tableView.make(withIdentifier: "NameCell", owner: self) as! NSTableCellView is keep failing because it returns nil

fatal error: unexpectedly found nil while unwrapping an Optional value

NameCell is from enter image description here Can anyone please help me find a way to solve this problem?

Uplift answered 12/6, 2017 at 9:55 Comment(3)
I think identifier I should give is correspond to NSTableColumn not NSTableCellViewUplift
Yes, I think those Identifier should be the identifier of NSTableColumn. Can you please explain how to make sure tableView is not nil (Watch the outlet)?Uplift
Did you change the identifier of both the column and the cell view?Dash
J
11

For anyone else who comes here with this same question when trying to make an NSTableView fully programmatically: makeView(withIdentifier:owner:) WILL return nil unless a corresponding NIB exists for the given identifier:

NSTableView documentation:

If a view with the specified identifier can’t be instantiated from the nib file or found in the reuse queue, this method returns nil.

Likewise, the 'owner' param is a NIB-specific concept. In short: you cannot use this method if populating your NSTableView with cells programmatically.

In this answer, I detail the Swift code to produce an NSTableCellView programmatically: https://mcmap.net/q/392667/-view-based-nsoutlineview-without-nib

However, if you don't want all the features of an NSTableViewCell, note that you can return any NSView in tableView(_:viewFor:row:). So you could, as per the CocoaProgrammaticHowtoCollection, simply write:

let cell = NSTextField()
cell.identifier = "my_id" // Essential! Allows re-use of the instance.
// ... Set any properties you want on the NSTextField.
return cell
Jeth answered 7/8, 2018 at 23:7 Comment(3)
The quote from the docs also says "or found in the reuse queue, this method returns nil." - so it should also work without a nib file - right?Tohubohu
@ChristianKienle I believe you would only be able to get an instance into the reuse queue in the first place by originally having instantiated a view from a nib. Maybe there is a way to do it entirely programmatically, but I'm not aware of it.Jeth
I also think that your assumption is 100% on point and this is also what I observe. But from reading the docs I think the method is just buggy... Because the table view has all the information it needs to actually properly re-use the cells. but it does not.Tohubohu
R
5

You should set the "Identifier" with "NameCell" in the NSTableCellView. And your codes should simplified as follow since the column's identifier won't change for ever:

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    var result: NSTableCellView
    let cell = tableView.make(withIdentifier: "NameCell", owner: self) as! NSTableCellView
    cell.textField?.stringValue = self.data[row].setting!

    return cell
}

references settings in XCode Interface Builder: enter image description here

Raglan answered 9/8, 2017 at 2:35 Comment(1)
Worked for me, but I had to use make(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "NameCell"), owner: self)Vaclav

© 2022 - 2024 — McMap. All rights reserved.