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):
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
}
}
CoreDataHandler.fetchCount()
does? – DionizBnumberOfRows
and inobjectValueFor
. Don't do that. It's unnecessarily expensive and inefficient. Fetch the stuff once and reload the table view or useNSFetchResultsController
and Cocoa Bindings. The latter reduces your code by 2/3. – vadiannumberof Rows
andobjectValueFor
, how do the tables get updated? – pdoakvar people = [Person]()
. Returnpeople.count
innumberOfRows
andpeople[row]
inobjectValueFor
. And replace(person.first ?? nil) ?? ""
withperson.first ?? ""
. The second nil-coalescing operator is redundant. – vadianarray[row]
inobjectValueFor
as I thought I had to return each column separately – pdoak