Search code examples
swiftmacosnstableview

Swift - Array to TableView in macOS


I have some data form a JSON file which I have converted into:

var tempArray = [NSDictionary]()

Here is what a sample of this data looks like:

(
    {
        active = y;
        "campaign_id" = "Sample ID 1";
        description = "Sample Text";
        "end_date_time" = "2017-10-01 00:00:00";
        "on_expiry" = ignore;
        "on_invalid_user" = reject;
        "start_date_time" = "2017-07-01 00:00:00";
        "voucher_code" = SAMPLEON1;
        "voucher_code_id" = "Sample ID 4";
    },
    {
        active = y;
        "campaign_id" = "Sample ID 2";
        description = "Sample Text";
        "end_date_time" = "2017-10-01 00:00:00";
        "on_expiry" = ignore;
        "on_invalid_user" = reject;
        "start_date_time" = "2017-06-02 00:00:00";
        "voucher_code" = SAMPLEOFF1;
        "voucher_code_id" = "Sample ID 5";
    }
)

I have a NSTableView outlet set up, and it has columns with identifiers relative to the dictionary above:

@IBOutlet var voucherTableView: NSTableView!

Once I run the voucherTableView.reloadData(); code in my Controller the table populates with the right amount of rows, but the data in the columns is all the same:

After reloadData

Here is my tableView func:

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



        let cellView = voucherTableView.make(withIdentifier: "cell", owner: self) as! NSTableCellView

        cellView.textField!.stringValue = self.values.object(at: row) as! String

        return cellView
    }

Does anyone have any insight into how to get the data from my Array into the tableView on the reload command?


Solution

  • I recommend to use Cocoa Bindings

    • Connect datasource of the table view in Interface Builder to the target class
    • Implement these two methods (viewForColumn:row is not needed)

      func numberOfRows(in tableView: NSTableView) -> Int
      {
          return tempArray.count
      }
      
      func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any?
      {
         return tempArray[row]
      }
      
    • In Interface Builder Bindings Inspector bind the value of the text field to Table Cell View > objectValue.[property] for example

      enter image description here

    Note: It's highly recommended to map the dictionaries to a custom class (a class inherited from NSObject is mandatory)