Swift 3.1 NSTableView – Different Approaches Sample Code

Created By: Debasis Das (22-May-2017)

In this post we will try the different approaches of handling data population in a NSTableView and rendering different content types in a NSTableView.

We will create NSTableViews which are

  • Simple Cell based NSTableView using Datasource
  • Simple View based NSTableView using Datasource
  • View Based NSTableView with different UI Elements in Columns
  • View Based NSTableView single column multiple UI Elements in Row
  • View Based NSTableView Single column Header Cell and Data Cell

Swift 3.1 Cell Based NSTableView
Switf 3.1 View Based NSTableView using Datasource
Switf 3.1 View Based NSTableView multiple column types
Swift 3.1 View Based NSTableView Single Column Multiple Cell type
Swift 3.1 View Based NSTableView Header Cell Data Cell

Swift 3.1 Cell Based NSTableView using Datasource

Swift 3.1 Cell Based NSTableView

//  ViewController.swift
//  CellBasedTableView
//  Created by Debasis Das on 5/15/17.
//  Copyright © 2017 Knowstack. All rights reserved.


import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var tableView:NSTableView!
    let tableViewData = [["firstName":"John","lastName":"Doe","emailId":"john.doe@knowstack.com"],["firstName":"Jane","lastName":"Doe","emailId":"jane.doe@knowstack.com"]]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self as? NSTableViewDelegate
        self.tableView.dataSource = self
    }
}

extension ViewController:NSTableViewDataSource{
    func numberOfRows(in tableView: NSTableView) -> Int {
        return tableViewData.count
    }
    
    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        return tableViewData[row][(tableColumn?.identifier)!]
    }
}

You can download the sample code here Simple Cell Based NSTableView

Swift 3.1 View Based NSTableView using Datasource

Switf 3.1 View Based NSTableView using Datasource

//  ViewController.swift
//  ViewBasedNSTableViewUsingDatasource
//  Created by Debasis Das on 5/15/17.
//  Copyright © 2017 Knowstack. All rights reserved.

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var tableView:NSTableView!
    let tableViewData = [["firstName":"John","lastName":"Doe","emailId":"john.doe@knowstack.com"],["firstName":"Jane","lastName":"Doe","emailId":"jane.doe@knowstack.com"]]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self as? NSTableViewDelegate
        self.tableView.dataSource = self
        self.tableView.reloadData()

    }

}

extension ViewController:NSTableViewDataSource, NSTableViewDelegate{
    func numberOfRows(in tableView: NSTableView) -> Int {
        return tableViewData.count
    }
    
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?{
        var result:NSTableCellView
        result  = tableView.make(withIdentifier: (tableColumn?.identifier)!, owner: self) as! NSTableCellView
            result.textField?.stringValue = tableViewData[row][(tableColumn?.identifier)!]!
        return result
    }

}

You can download the sample code here Simple View Based NSTableView Using Datasource

Swift 3.1 View Based NSTableView – Different UI Elements in Columns

Switf 3.1 View Based NSTableView multiple column types

//  ViewController.swift
//  ViewBasedTable-MultiCellTypes
//  Created by Debasis Das on 5/15/17.
//  Copyright © 2017 Knowstack. All rights reserved.

import Cocoa

class ViewController: NSViewController {
    @IBOutlet weak var tableView:NSTableView!
    var tableViewData = [["firstName":"John","lastName":"Doe","imageIcon":"NSUser","jobTitle":"PM"],
        ["firstName":"Jane","lastName":"Doe","imageIcon":"NSUserGroup","jobTitle":"SE"],]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self
        self.tableView.dataSource = self

    }

}

extension ViewController:NSTableViewDataSource, NSTableViewDelegate{
    func numberOfRows(in tableView: NSTableView) -> Int {
        return tableViewData.count
    }
    
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?{
        if tableColumn?.identifier == "imageIcon"{
            let result = tableView.make(withIdentifier: "imageIcon", owner: self) as! NSTableCellView
            result.imageView?.image = NSImage(named:tableViewData[row]["imageIcon"]!)
            return result
        }
        else if tableColumn?.identifier == "jobTitle"{
            let result:NSPopUpButton = tableView.make(withIdentifier: "jobTitle", owner: self) as! NSPopUpButton
            result.selectItem(withTitle: tableViewData[row]["jobTitle"]!)
            return result
        }
        else{
            let result = tableView.make(withIdentifier:(tableColumn?.identifier)!, owner: self) as! NSTableCellView
            result.textField?.stringValue = tableViewData[row][(tableColumn?.identifier)!]!
            return result
        }
    }
}

You can download the sample code here ViewBased NSTableView-Multiple Cell Types

Swift 3.1 View Based NSTableView – Single Column – Multiple UI Elements in a row

Swift 3.1 View Based NSTableView Single Column Multiple Cell type

//  ViewController.swift
//  ViewBasedTable-SingleColumn-MultiCell
//  Created by Debasis Das on 5/15/17.
//  Copyright © 2017 Knowstack. All rights reserved.

import Cocoa

class ViewController: NSViewController {
    @IBOutlet weak var tableView:NSTableView!
    var tableViewData = [["imageIcon":"NSUser","summaryInfo":"This is high level summary","descriptionInfo":"Some More Description","detailInfo":"Detailed Information"],["imageIcon":"NSUser","summaryInfo":"Product 2 - This is high level summary","descriptionInfo":"Some More Description","detailInfo":"Detailed Information"]]

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self
        self.tableView.dataSource = self
    }
}


extension ViewController:NSTableViewDataSource, NSTableViewDelegate{
    func numberOfRows(in tableView: NSTableView) -> Int {
        return tableViewData.count
    }
    
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?{
        let result:KSTableCellView = tableView.make(withIdentifier: "defaultRow", owner: self) as! KSTableCellView
        result.imgView.image = NSImage(named:"NSUser")
        result.summaryTextField.stringValue = tableViewData[row]["summaryInfo"]!
        result.descriptionTextField.stringValue = tableViewData[row]["descriptionInfo"]!
        result.detailsTextField.stringValue = tableViewData[row]["detailInfo"]!
        return result;
     }
}

class KSTableCellView: NSTableCellView {

    @IBOutlet weak var imgView: NSImageView!
    @IBOutlet weak var summaryTextField: NSTextField!
    @IBOutlet weak var descriptionTextField: NSTextField!
    @IBOutlet weak var detailsTextField: NSTextField!
}

You can download the sample code here View Based NSTableView-SingleColumn-MultiCell

Swift 3.1 View Based NSTableView – Single Column – Different Header Cell and Data Cell

Swift 3.1 View Based NSTableView Header Cell Data Cell

//  ViewController.swift
//  ViewController.swift
//  ViewBasedTable-HeaderCell-DataCell
//  Created by Debasis Das on 5/15/17.
//  Copyright © 2017 Knowstack. All rights reserved.

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var tableView:NSTableView!
    
    var tableViewData = [["headerInfo":"iPad"],
    ["summaryInfo":"iPad Pro","detailInfo":"This is a very long description about iPad Pro.iOS 9 brings key enhancements to the powerful built-in apps you use every day. And new multitasking features help make you even more productive.","imageIcon":"NSStatusUnavailable"],
    ["summaryInfo":"iPad Air","detailInfo":"This is a very long description about iPad Air.iOS 9 brings key enhancements to the powerful built-in apps you use every day. And new multitasking features help make you even more productive.","imageIcon":"NSStatusAvailable"],
    ["headerInfo":"CPU"],
    ["summaryInfo":"Mac Mini","detailInfo":"This is a very long description about Mac Mini","imageIcon":"NSStatusPartiallyAvailable"]
    ]
 
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self
        self.tableView.dataSource = self
    }
}


extension ViewController:NSTableViewDataSource, NSTableViewDelegate{
    func numberOfRows(in tableView: NSTableView) -> Int {
        return tableViewData.count
    }
    
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?{

        if tableViewData[row]["headerInfo"] != nil{
            //Header Row
            let result = tableView.make(withIdentifier: "HeaderRow", owner: self) as! KSHeaderCellView
            result.headerInfoTextField.stringValue = tableViewData[row]["headerInfo"]!
            return result
        }
        else{
            //Data Row
            let result = tableView.make(withIdentifier: "DataRow", owner: self) as! KSDataCellView
            result.summaryTextField.stringValue = tableViewData[row]["summaryInfo"]!
            result.detailsTextField.stringValue = tableViewData[row]["detailInfo"]!
            result.imageView?.image = NSImage(named: tableViewData[row]["imageIcon"]!)

            return result
        }
    }
    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
        if tableViewData[row]["headerInfo"] != nil{
            return 27.0
        }
        else{
            return 67.0
        }
        
    }
    
}
class KSDataCellView: NSTableCellView {

    @IBOutlet weak var summaryTextField:NSTextField!
    @IBOutlet weak var detailsTextField:NSTextField!
    
    
}
class KSHeaderCellView: NSTableCellView {
    
    @IBOutlet weak var headerInfoTextField:NSTextField!
    
    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
        let bPath:NSBezierPath = NSBezierPath(rect: dirtyRect)
        let fillColor = NSColor(red: 0.7, green: 0.7, blue: 0.5, alpha: 1.0)
        fillColor.set()
        bPath.fill()
    }

}

You can download the sample code here ViewBased NSTableView-HeaderCell-DataCell

Posted in Swift 3.1 Tagged with:
3 comments on “Swift 3.1 NSTableView – Different Approaches Sample Code
  1. Claude Merger-Steinmetz says:

    Hi Das, I am new to cocoa and swift. I have been looking for a good tutorial on MacOS tableView for the last few weeks. None was clear enough until I found yours.
    I do not know if this is the right place to ask a question but I get an error when implementing tableView. I have a table which is 1000 rows x 11 columns filled with string data. Each column has a header.
    on this line of code :
    cellContent.textField?.stringValue = journal[row][(tableColumn?.identifier)!]!
    I get the following error:
    cannot subscript a value of type ‘[String]’ with an index of type ‘String’

    The data source ‘journal’ is an array of String: var journal[[String]] that I load from my model

    Any hint on how to solve that?
    Thanks.

  2. Olivier D. says:

    Hi,
    Many Thanks for this tuto! Great! It’s so difficult to find a tuto for MacOS!

1 Pings/Trackbacks for "Swift 3.1 NSTableView – Different Approaches Sample Code"
  1. […] read http://www.knowstack.com/swift-3-1-nstableview-complete-guide/ for checking the different approaches of loading a NSTableView in Swift […]

Leave a Reply

Your email address will not be published. Required fields are marked *

*