Reputation: 593
I have a macOS Monterrey app that has a TextField
on the toolbar. I use this to search for text on my app. Now, I'm trying to add a keyboard shortcut to focus on the TextField
. I've tried the code below, adding button with a shortcut as a way to test whether this is doable, but I can't get it to work. The .focused()
doesn't do anything.
Beyond that, I have added a new menu item Find
and set the keyboard shortcut to cmd-L but I don't know either how to send the focus to the TextField.
What am I missing?
struct AllData: View {
@FocusState private var searchFieldIsFocused: Bool
@State var searchText: String = ""
var body: some View {
NavigationView {
List(data.notes.filter { searchText.isEmpty ? true : $0.text.localizedCaseInsensitiveContains(searchText) }) {
//...
}
}
.navigationTitle("A Title")
.toolbar {
ToolbarItem(placement: .automatic) {
TextField("Search...", text: $searchText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(minWidth: 200)
.focused($searchFieldIsFocused)
}
//test for the focus
ToolbarItem(placement: .automatic) {
Button(action: {
print("Plus pressed")
searchFieldIsFocused = true
}) {
Image(systemName: "plus")
}
.keyboardShortcut("e", modifiers: [.command])
}
}
}
}
Edit after Yrb comments
It seems .focusable
will not work with a TextField
on a toolbar, so he suggested using .searchable
.
Trying with .searchable
struct AllData: View {
@FocusState private var searchFieldIsFocused: Bool
@State var searchText: String = ""
var body: some View {
NavigationView {
List(data.notes.filter { searchText.isEmpty ? true : $0.text.localizedCaseInsensitiveContains(searchText) }) {
//...
}
.searchable(
text: $searchText,
placement: .toolbar,
prompt: "Search..."
)
}
.navigationTitle("A Title")
.toolbar {
//test for the focus
ToolbarItem(placement: .automatic) {
Button(action: {
print("Plus pressed")
searchFieldIsFocused = true
}) {
Image(systemName: "plus")
}
.keyboardShortcut("e", modifiers: [.command])
}
}
}
}
Observations:
.focusable
so I can jump to the search with a keyboard shortcut, which is the reason for this questionI'm sure I'm missing something, and probably my code is wrong. Any clues?
Edit #2
It seems this is not possible with a .searchable
:
.searchable modifier with a keyboard shortcut
Upvotes: 6
Views: 1111
Reputation: 56
I ended up getting the following to work on macOS
using the .searchable()
modifier (only tested on macOS 12.3
):
import SwiftUI
@main
struct MyApp: App {
@State var searchText = ""
var items = ["Item 1", "Item 2", "Item 3"]
var searchResults: [String] {
if searchText.isEmpty {
return items
} else {
return items.filter { $0.contains(searchText) }
}
}
var body: some Scene {
WindowGroup {
List(self.searchResults, id: \.self) { item in
Text(item)
}.searchable(text: self.$searchText)
}.commands {
CommandMenu("Find") {
Button("Find") {
if let toolbar = NSApp.keyWindow?.toolbar,
let search = toolbar.items.first(where: { $0.itemIdentifier.rawValue == "com.apple.SwiftUI.search" }) as? NSSearchToolbarItem {
search.beginSearchInteraction()
}
}.keyboardShortcut("f", modifiers: .command)
}
}
}
}
Upvotes: 4