0

I'm a bit stumped on how to reload a NSTableView's data upon a searchField's text changing. I assumed that I needed to filter the array that the tableView uses to populate itself based upon string matching and the call tableView.reloadData() all inside of controlTextDidChange() but when I test the code it doesn't work. I'm assuming that this will be a pretty simple fix and most of the info I've found on this topic has been a bit complicated. So I don't know how simple or complicated the solution really is

Here is my controlTextDidChange() func:

func controlTextDidChange(_ obj: Notification) {
    noteRecords.filter { $0.title.contains(searchField.stringValue) }
    tableView.reloadData()
}

If someone could please explain how to reload the tableViews data using the filtered array upon the searchField's text changing that would be very much appreciated. Also if it's easier to replace the searchField with a plain NSTextField let me know.

Edit

here's the func that populates the tableView:

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
    let note = allRecords[row]
    let cellIdentifier = NSUserInterfaceItemIdentifier(rawValue: "NoteInCloudCell")
    
    if tableColumn == tableView.tableColumns[0] {
        let cell = tableView.makeView(withIdentifier: cellIdentifier, owner: nil) as? NoteInCloudCell
        cell?.noteTitle.stringValue = note.title
        cell?.cloudID.stringValue = note.cloudID
        return cell
    }
    else { return nil }
}
JonGrimes20
  • 115
  • 9

1 Answers1

1

Create a second array of the same type as noteRecords and name it allRecords

Assign the complete set of records to allRecords and use noteRecords as data source array

Replace controlTextDidChange with

func controlTextDidChange(_ obj: Notification) {
    let query = searchField.stringValue
    if query.isEmpty {
        noteRecords = allRecords
    } else {
        noteRecords = allRecords.filter { $0.title.localizedCaseInsensitiveContains(query)
    }
    tableView.reloadData()
}

A more sophisticated way is a diffable data source.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • I'm a bit confused on what you mean by using ```noteRecords``` as data source array can you please provide a bit more detail on that part? I've edited the question to show the tableView func that populates the table. – JonGrimes20 Mar 18 '22 at 18:34
  • My suggestion requires two arrays of the same type. Array #1 contains all items and will never be modified. Array #2 works as the data source array in `numberOfRows` and `viewFor:row:` and is populated somewhere at the beginning and while seraching. In your code `allRecords` is the data source array, so use the other array for holding all items. – vadian Mar 18 '22 at 18:43
  • Thank you very much, I was having trouble because I was setting noteRecords = allRecords in the wrong spot. Once I set it inside of the Task block where I query all records it worked – JonGrimes20 Mar 18 '22 at 18:49