4
votes

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?

2
I think identifier I should give is correspond to NSTableColumn not NSTableCellView - user3284302
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)? - user3284302
Did you change the identifier of both the column and the cell view? - Willeke

2 Answers

9
votes

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://stackoverflow.com/a/51736468/5951226

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
5
votes

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