Search code examples
swiftnstableview

NSTableView not updating on initial loading


I have an NSView with a NSTableView called personTableView. In the ViewController class, I have the following code:

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    personTableView.delegate = self
    personTableView.dataSource = self
    personTableView.reloadData()

}

and have extended the class to with NSTableViewDelegate and NSTableViewDataSource

However, when the view appears, the table shows the following (there are only 2 entries that the table should display):

enter image description here

On my window, I have a button which invokes the following action:

@IBAction func refreshButton(_ sender: NSButton) {
    let result = CoreDataHandler.fetchCount()
    print("Row Count:\(result)")
    personTableView.reloadData()
    codeTableView.reloadData()
}

which when pressed, populates my TableView. I don't understand why it won't load automatically?

I have also tried putting the personTableView.reloadData() into viewWillAppear and viewDidAppear to no avail.

Update:

This is the fetchCount():

static func fetchCount() -> Int {
    let context = getContext()
    do {
        let count = try context.count(for: Person.fetchRequest())
        NSLog("Count from fetchCount: %d", count)
        return count
    } catch {
        return 0
    }
}

For information, this is the Table Delegate and DataSource functions:

extension ViewController: NSTableViewDataSource {
    func numberOfRows(in tableView: NSTableView) -> Int {
        if tableView == self.personTableView {
            let result = CoreDataHandler.fetchCount()
            //NSLog("Rows in Ext: %@",result)
            return result
        }
        if tableView == self.codeTableView {
            let row = personTableView.selectedRow
            if row > -1 {
                let person = CoreDataHandler.fetchPerson()?[row]
                print("Person= \(String(describing: person?.first))")
                //let result = CoreDataHandler.fetchCodes(person: person!)
                let result = person?.codes
                //print("Person from result: \(String(describing: result?.first.whosAccount?.ibAccount))")
                let count = result!.count
                print("Rows in Codes from viewController dataSource: \(count)")
                return count
            } else {
            return 0
            }
        }
        return 0
    }
}

extension ViewController: NSTableViewDelegate {

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

        if tableView == self.personTableView {
            guard let person = CoreDataHandler.fetchPerson()?[row] else {
                return nil
            }

            if let cell = tableView.makeView(withIdentifier: (tableColumn!.identifier), owner: nil) as? NSTableCellView {
                if tableColumn == tableView.tableColumns[0]  {
                    cell.textField?.stringValue = (person.first ?? nil) ?? ""
                } else if tableColumn == tableView.tableColumns[1] {
                    cell.textField?.stringValue = (person.last ?? nil) ?? ""
                } else {
                    cell.textField?.stringValue = (person.ibAccount ?? nil) ?? ""
                }

                return cell

            } else {
                return nil
            }
        }

        if tableView == self.codeTableView {

            let personRow = personTableView.selectedRow
            if personRow > -1 {
                let person = CoreDataHandler.fetchPerson()?[personRow]
                guard let code = CoreDataHandler.fetchCodes(person: person!)?[row] else {
                    return nil
                }

                if let cell = tableView.makeView(withIdentifier: (tableColumn!.identifier), owner: nil) as? NSTableCellView {
                    if tableColumn == tableView.tableColumns[0]  {
                        cell.textField?.stringValue = (String(code.number) )
                        //cell.textField?.stringValue = person?.codes?.allObjects[row] as! String
                    } else if tableColumn == tableView.tableColumns[1] {
                        cell.textField?.stringValue = code.code!

                    } else if tableColumn == tableView.tableColumns[2] {
                        cell.textField?.stringValue = (code.whosAccount?.ibAccount ?? "")
                    }

                    return cell

                } else {
                    return nil
                }
            }
        }

        return nil

    }



}

Solution

  • You've mixed up tableView(_:objectValueFor:row:) of NSTableViewDataSource and tableView(_:viewFor:row:) of NSTableViewDelegate. Replace

    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any?
    

    by

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

    or return strings from tableView(_:objectValueFor:row:)