Search code examples
swiftmacosnstableviewnssearchfieldtablefilter

Swift - programmatically trigger NSSearchField filtering



I'm writing a table-based app for MacOS (using NSTableView).

To implement table filtering, I use bindings.

In my app I have a NSTableView that I bind to a NSArrayController, and a NSSearchField that I bind to that same array controller. This is my code for binding these objects:

self.tableView.bind(.content, to: self.arrayController, withKeyPath: "arrangedObjects", options: nil)
let searchField = (Constants.appDelegate.SearchFieldVC.view as? NSSearchField)!  // grab searchField reference
searchField.bind(
    .predicate,
    to: self.arrayController,
    withKeyPath: NSBindingName.filterPredicate.rawValue,
    options: [.predicateFormat: "col CONTAINS[cd] $value"]
)

where col is the name of my tableView column that I want the search field to filter.

Everything works perfectly fine; when I type text into my search field it filters the table accordingly.
The problem emerges when I try to programmatically "inject" text into my search field.
This is the code I use to do that:

self.view.window?.makeFirstResponder(searchField) // move focus from tableView to searchField
searchField?.stringValue.append(someString)  // inject some text into searchField, expecting immediate table filtering
searchField?.currentEditor()?.moveToEndOfLine(self)

Meaning - I make my searchField the first responder (moving "focus" from the table view to the search field), then write some text into the search field's stringValue.

When I run the application, I can see the "focus" moving to my searchField and the text being written into it, but no filtering is being executed. I have to either manually press "Enter" or keep typing inside the searchField for the filter to execute correctly.

How can I programmatically inject text into my searchField AND execute it's filtering capabilities immediately?
Thanks!


Solution

  • The binding is triggered by the action.

    searchField.sendAction(searchField.action, to: searchField.target)
    

    searchField.action and searchField.target can be nil.