2

I am trying to build a table view without interface builder from scratch in my Cocoa app and my viewForTableColumn method refuses to get called.

My table view is created using this code.

let tableView: NSTableView = {
    let table = NSTableView(frame: .zero)
    table.headerView = nil
    table.addTableColumn(NSTableColumn(identifier: .column))

    return table
}()

I also have this extension for the NSUserInterfaceItemIdentifier class

extension NSUserInterfaceItemIdentifier {
    static let cell = NSUserInterfaceItemIdentifier("cell")
    static let column = NSUserInterfaceItemIdentifier("column")
}

My view controller is implementing NSTableViewDataSource and NSTableViewDelegate and they are set in the viewDidLoad method. The table view is also into a scroll view.

let scrollView = NSScrollView()

override func viewDidLoad() {
    self.scrollView.documentView = self.tableView
    self.scrollView.hasVerticalScroller = true
    self.view.addSubview(self.scrollView)

    self.tableView.delegate = self
    self.tableView.dataSource = self
    self.tableView.reloadData() // To make sure the method would be called.
}

The value returned from the numberOfRows method is bigger than 0 and is executed.

From my understanding the following method should be called with the row parameter ranging from 0 to the value returned by numberOfRows but it's never being called.

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    guard let view = self.tableView.makeView(withIdentifier: .cell, owner: self) as? NSTableCellView else {
        return nil
    }

    // set the text/font for the view

    return view
}

I've also tried using dataCellFor and rowViewForRow but none of them is getting called.

EDIT:

I've checked the frame of my elements to make sure the table view and the rows were visible.

view hierarchy

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
afrigon
  • 47
  • 1
  • 7
  • 2
    An invisible table view doesn't ask for views. What is the the frame of `scrollView`? – Willeke Dec 05 '18 at 07:16
  • The frame is set to the size of the window, setting the background color to red confirms that it is visible. – afrigon Dec 05 '18 at 07:18
  • Are the frame of the table view and the width of the column also ok? If you capture the view hierarchy, is the table view visible? – Willeke Dec 05 '18 at 07:36
  • I've added a picture of the view hierarchy, the blue view is the `scrollView` and the red is the `tableView` – afrigon Dec 05 '18 at 07:46
  • I tried your code (added `self.scrollView.frame = self.view.bounds` and `numberOfRowsInTableView`) and `viewForTableColumn` is called. It returns `nil`. – Willeke Dec 05 '18 at 08:40
  • Do you think it could be something external in my setup? The code should work like you mentioned. This view is in a second `NSWindow` but it probably should still work just fine. – afrigon Dec 05 '18 at 09:04
  • I answered a [similar question](https://stackoverflow.com/questions/33992756/is-it-possible-to-create-a-view-based-nstableview-purely-in-code) a while back - perhaps it can help – Paul Patterson Dec 05 '18 at 11:10
  • @PaulPatterson Your code looks a lot like mine, not sure what would be the cause of my problem. – afrigon Dec 05 '18 at 11:34

1 Answers1

0

According to one of the comments beneath your question tableView(_:viewFor:row:) is being called, it's just returning nil. This makes sense given your implementation of that method. When makeViewWithIdentifier fails you need to manually create the relevant view and return it, rather than returning nil. As such your implementation should look something like this:

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {

    if let recycledView = self.tableView.makeView(withIdentifier: .cell, owner: self) as? NSTableCellView {
        return recycledView
    } else {
        // create view from scratch
        let newCell = NSTableCellView()
        newCell.identifier = NSUserInterfaceItemIdentifier.cell
        // customise here...
        return newCell
    }
}

Look again at the link I provided in my comment, you'll see that that implementation never returns nil from this method.

afrigon
  • 47
  • 1
  • 7
Paul Patterson
  • 6,840
  • 3
  • 42
  • 56
  • I tried putting a print and a breakpoint in there and none of it was triggered. I've fix my problem now, still not sure what was wrong, I rewrote the entire `NSWindow` the only difference is that I took out the `NSViewController`. Thanks for your answer. – afrigon Dec 05 '18 at 21:11