swiftnstableviewnstextfieldnssearchfield

How to reload NSTableView data when NSSearchField text changes


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 }
}

Solution

  • 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.