Differentiating between "return" and focus loss in TextField onCommit

I have a TextField in my toolbar that I use for a search function. I want to trigger the search by hitting the "return" key in this field. But if I do it in onCommit, the search also gets triggered when the user un-focuses the field.

Is there a way to respond to just the "return" key?

Code Block
TextField("Search", text: $searchQuery) { editing in
print("onEditingChanged \(editing)")
} onCommit: {
// Problem: this is triggered by both
// 1. Return key
// 2. Losing focus
    searchModel.startSearch(query: searchQuery)
}

Yes.
Use the keydboardShortcut view modifier.

(Here on a Button, but the principle is the same)
Code Block
Button("Login", action: onLoginAction)   
.keyboardShortcut(.defaultAction)

Sorry, I don't follow. There is no action: parameter for TextField, so what is would get triggered by the keyboard shortcut? I tried putting the modifier on it anyway, but the behavior is the same.

Code Block
TextField("Search", text: $searchQuery) { editing in
....
} onCommit: {
... // still triggered by return OR focus loss
}.keyboardShortcut(.defaultAction)


I ended up using NSViewRepresentable and wrapping an NSTextField. So I have something working now, but I'd prefer to use pure SwiftUI if I can.


Try this:

Code Block
        ZStack {
            Button("") {
                searchModel.startSearch(query: searchQuery)
            }
            .keyboardShortcut(.defaultAction)
            TextField("Search", text: $searchQuery)
        }


Maybe I don't understand the question properly, but I'm not getting a "onCommit" trigger
when changing the focus. Using xcode 12.5-beta, macos 11.3-beta, targets ios 14.x, catalyst 11.3
with the following test code:

Code Block
struct ContentView: View {
@State var searchQuery1 = ""
@State var searchQuery2 = ""
var body: some View {
VStack {
TextField("TextField 1", text: $searchQuery1){ _ in print("changed 1") }
onCommit: { print("-----> commit 1") } // only when the return key is pressed
// another TextField to change focus
TextField("TextField 2", text: $searchQuery2,
onEditingChanged: { _ in print("changed 2") },
onCommit: { print("commit 2") }
)
// a button to change focus
Button(action: {print("button action")}) {
Text("button")
}
}
}
}

Workingdogintokyo, it sounds like maybe this has changed in macOS 11.3 beta. I'm running 11.2.3. I pasted your example into a fresh project, and here is the output I get when I start the app, click in the 1st text field, then click in the 2nd text field.

Code Block
changed 1
-----> commit 1





robnotyou, your example with the ZStack partly works for me. The return key triggers the behavior, but the problem is the Button is still visible, as a small blue rounded rectangle, behind the (apparently transparent) TextField.

I'm satisfied with wrapping NSTextField for now. It has some properties and delegate callbacks to more precisely control this behavior.
definitely things have changed in macOS 11.3 beta. This is what I get when I start the app, click in the 1st text field, then click in the 2nd text field. I never get any "commit" unless I press the return key.
Code Block
changed 1
changed 1
changed 2

Differentiating between "return" and focus loss in TextField onCommit
 
 
Q