You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SwiftUI .searchable修饰符添加⌘F搜索快捷键支持

编辑

iOS 17及以上版本已有原生支持的实现方案。

原帖内容

.searchable视图修饰符是iOS 15 SwiftUI 3.0推出的新特性之一,下方是其基础使用示例。我希望能像大多数应用一样,实现按下⌘F触发搜索的功能,请问该如何实现?据我所知.keyboardShortcut修饰符仅能用于Button视图,限制较大,是否有可行的实现方式或替代方案?谢谢!

struct ContentView: View {
    @State var searchText = ""
    private let fruits = ["apple", "banana", "plum", "grape"]
    
    var filteredFruits: [String] {
        if !searchText.isEmpty {
             return fruits.filter { $0.starts(with: searchText.lowercased()) }
        } else {
            return fruits
        }
    }

    var body: some View {
        NavigationView {
            List {
                ForEach(filteredFruits, id: \.self) { fruit in
                    Text(fruit.capitalized)
                }
            }
            .navigationBarTitle("Search")
            .searchable(text: $searchText) // Need to add key command to search (⌘F)
        }
    }
}

实现方案

iOS 17+ 版本实现

iOS 17新增了搜索框焦点绑定能力,配合@FocusState和快捷键即可实现:

struct ContentView: View {
    @State var searchText = ""
    @FocusState var isSearchFocused: Bool
    private let fruits = ["apple", "banana", "plum", "grape"]
    
    var filteredFruits: [String] {
        if !searchText.isEmpty {
             return fruits.filter { $0.starts(with: searchText.lowercased()) }
        } else {
            return fruits
        }
    }

    var body: some View {
        // iOS16及以上推荐用NavigationStack替代NavigationView
        NavigationStack {
            List {
                ForEach(filteredFruits, id: \.self) { fruit in
                    Text(fruit.capitalized)
                }
            }
            .navigationTitle("Search")
            .searchable(text: $searchText, isPresented: $isSearchFocused)
            .focused($isSearchFocused)
            // 添加隐藏的快捷键触发按钮
            .background {
                Button("") {
                    isSearchFocused = true
                }
                .keyboardShortcut("f", modifiers: .command)
                .opacity(0)
            }
        }
    }
}

iOS 15 ~ iOS 16 兼容版本

低版本没有原生的搜索框焦点绑定接口,可以通过遍历响应者链的方式激活搜索框:

extension UIApplication {
    func activateSearchBar() {
        guard let window = connectedScenes
                .filter({ $0.activationState == .foregroundActive })
                .compactMap({ $0 as? UIWindowScene })
                .first?.windows
                .first(where: \.isKeyWindow) else { return }
        
        // 遍历视图树找到UISearchBar实例
        func findSearchBar(in view: UIView) -> UISearchBar? {
            for subview in view.subviews {
                if let searchBar = subview as? UISearchBar {
                    return searchBar
                } else if let found = findSearchBar(in: subview) {
                    return found
                }
            }
            return nil
        }
        
        findSearchBar(in: window)?.becomeFirstResponder()
    }
}

// 主视图代码
struct ContentView: View {
    @State var searchText = ""
    private let fruits = ["apple", "banana", "plum", "grape"]
    
    var filteredFruits: [String] {
        if !searchText.isEmpty {
             return fruits.filter { $0.starts(with: searchText.lowercased()) }
        } else {
            return fruits
        }
    }

    var body: some View {
        NavigationView {
            List {
                ForEach(filteredFruits, id: \.self) { fruit in
                    Text(fruit.capitalized)
                }
            }
            .navigationBarTitle("Search")
            .searchable(text: $searchText)
            .background {
                Button("") {
                    UIApplication.shared.activateSearchBar()
                }
                .keyboardShortcut("f", modifiers: .command)
                .opacity(0)
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Denny L.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 21:09:03