Displaying Data in a Mac Table View

Displaying data in a Mac table view has the following requirements:

  • Data to display.
  • Make the table view controller conform to the NSTableViewDelegate and NSTableViewDataSource protocols.
  • Write the function numberOfRows.
  • Write the function viewForTableColumn.
  • Set the table view’s data source and delegate.

Data to Display

A table view needs data to display. Usually table view data is in an array. As an example, suppose you have a note-taking app with a struct for a note.

struct Note {
    var title: String = ""
    var contents: String = ""
}

You will have an array of notes to display in the table view.

var notes = [Note]()

Conform to Delegate and Data Source Protocols

To make a Swift class or struct conform to protocols, add a colon after the name of the struct/class and add the protocol names, separated by commas. It’s similar to inheriting from a class.

The following code shows how to declare a class extension for a table view controller that conforms to the required protocols, NSTableViewDelegate and NSTableViewDataSource:

extension TableViewController: NSTableViewDelegate, NSTableViewDataSource {
    // Place the data source and delegate functions
    // inside the extension.
}

numberOfRows

The first function you must write is numberOfRows, which returns the number of rows in the table view. The number of rows is going to equal the number of items in the data source array. The following code shows an example of the numberOfRows function for a note-taking app:

func numberOfRows(in aTableView: NSTableView) -> Int {
    return notes.count
}

viewForTableColumn

The second function you must write is viewForTableColumn, which returns the view for a table view column.

Before you write code, you need to enter an identifier for the table column so you can load the cell from the storyboard. Open the storyboard, select the table column, and open the identity inspector. Enter an identifier for the column in the Identifier text field.

TableColumnIdentifier

Remember the identifier you used because you’re going to need it when you write viewForTableColumn.

Now you can write the viewForTableColumn function. The function will create the table view cell from the storyboard by calling the NSTableView method makeView. After creating the table view cell, set the cell’s text field contents to the data you want to display in the cell.

The following code demonstrates how to display a note’s title in the table column:

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

    guard let cellView = tableView.makeView(withIdentifier: 
        NSUserInterfaceItemIdentifier(rawValue: "TitleColumn"), 
        owner: self) as? NSTableCellView 
    else {
        return nil   
    }

    cellView.textField?.stringValue = notes[row].title
    return cellView      
}

The guard statement says to return nil if a user interface element with the raw value of TitleColumn, the identifier you set in the storyboard, is not found in the storyboard. If the element is found, set the cell’s text field to display the title of the note at subscript row in the notes array, then return the cell’s view.

Set the Table View’s Data Source and Delegate

The last step is to set the table view’s data source and delegate to the table view’s view controller. Setting the data source and delegate allows the functions numberOfRows and viewForTableColumn to be called when loading the table view controller.

Open the storyboard and make a connection from the table view to the table view’s view controller. A HUD like the following will open:

TableViewDelegateHUD

Select dataSource. Repeat the connection and select delegate.