SwiftUI 的 searchable 修饰符用于在视图中轻松实现搜索功能,为用户提供一种快速查找内容的方式。它可以与列表、滚动视图或其他复杂的视图组合使用,简化了搜索功能的开发。
基本语法
.searchable(text: Binding<String>, prompt: String? = nil, placement: SearchFieldPlacement = .automatic)
参数
1、text:
一个绑定的字符串,用于存储用户输入的搜索内容。
通常是通过 @State 或 @Binding 声明的变量。
2、prompt:
可选参数,为搜索框提供占位符文本,帮助用户理解需要输入什么。
3、placement:
定义搜索框的位置。
类型为 SearchFieldPlacement,可以是以下值:
.automatic:根据平台的最佳实践自动决定。
.navigationBarDrawer(displayMode:):将搜索框放在导航栏中,显示方式可以是 .always 或 .automatic。
.toolbar:将搜索框添加到工具栏中。
简单示例
搜索一个静态列表
struct ContentView: View {
@State private var searchText = ""
let items = ["Apple", "Banana", "Cherry", "Date", "Fig", "Grape"]
var filteredItems: [String] {
if searchText.isEmpty {
return items
} else {
return items.filter { $0.localizedCaseInsensitiveContains(searchText) }
}
}
var body: some View {
NavigationStack {
List(filteredItems, id: \.self) { item in
Text(item)
}
.searchable(text: $searchText, prompt: "Search fruits")
.navigationTitle("Fruits")
}
}
}
高级功能
自定义搜索框位置
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
让搜索框始终显示在导航栏中。
使用建议项
searchable 可以支持动态建议,当用户输入内容时提供自动补全的选项:
struct ContentView: View {
@State private var searchText = ""
let allItems = ["Swift", "SwiftUI", "Combine", "UIKit", "Objective-C"]
var suggestions: [String] {
if searchText.isEmpty {
return []
} else {
return allItems.filter { $0.localizedCaseInsensitiveContains(searchText) }
}
}
var body: some View {
NavigationStack {
List {
ForEach(suggestions, id: \.self) { suggestion in
Text(suggestion)
.onTapGesture {
searchText = suggestion
}
}
}
.searchable(text: $searchText, prompt: "Search terms")
.navigationTitle("Searchable Example")
}
}
}
当用户在搜索框中输入内容时,可以动态显示建议项(autocomplete),帮助用户快速选择。
监听搜索状态
可以通过 .onChange(of:) 来监听搜索文本的变化:
.onChange(of: searchText) { newValue in
print("Search text changed to: \(newValue)")
}
动态调整搜索行为
通过条件动态调整搜索逻辑,例如区分大小写搜索、延迟搜索等。
示例:延迟搜索
@State private var debouncedText = ""
@State private var searchText = ""
.onChange(of: searchText) { newValue in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
if newValue == searchText {
debouncedText = newValue
}
}
}
在 iOS 和 macOS 上的差异化
iOS:
搜索框通常显示在导航栏或列表顶部。
支持自动隐藏和动态显示。
macOS:
搜索框更常用于工具栏。
支持快捷键触发(如 Command + F)。
与NavigationStack搭配
在 SwiftUI 中,searchable 通常需要与 NavigationStack 或 NavigationView 一起使用,特别是在构建包含导航功能的应用时。这样做的原因是,searchable 的默认行为和外观在导航上下文中表现最佳,尤其是在 iOS 上。
与 NavigationStack 的关系
1、显示位置的优化:
当 searchable 与 NavigationStack 一起使用时,搜索框通常嵌入到导航栏的合适位置。这是系统为提升用户体验而优化的结果。
如果没有 NavigationStack,搜索框会在当前视图顶部显示,但无法利用导航栏的显示效果。
2、导航功能的增强:
NavigationStack 为视图提供了导航能力(如标题、返回按钮)。
搜索通常是列表视图的一部分,而 NavigationStack 为列表视图提供更符合 Apple Human Interface Guidelines 的外观和行为。
3、状态管理的整合:
搜索功能依赖于 Binding(如 $searchText),而导航堆栈可以帮助协调多个视图之间的状态。
注意事项
1、NavigationStack 是推荐的导航方式:
在 SwiftUI 中,NavigationStack 是比 NavigationView 更现代、更强大的导航工具。
它支持数据驱动的导航栈,适合复杂导航需求。
不搭配NavigationStack 或 NavigationView,可能无法使用searchable。
2、macOS 的特殊情况:
在 macOS 上,搜索框通常显示在工具栏中,而不是导航栏。
与 NavigationStack 搭配时,searchable 会自动调整搜索框的位置和样式,提供最佳用户体验。
如果需要完整的导航功能和上下文管理,建议始终使用 NavigationStack 或类似的导航结构。
对于简单的列表过滤或搜索功能,可以不使用 NavigationStack,但会失去导航栏的整合效果。
适用平台
iOS: searchable 会在导航栏或列表顶部提供一个搜索框。
macOS: 搜索框会显示在工具栏中。
watchOS 和 tvOS: 尚不支持。
总结
searchable 是一个简单而强大的搜索功能修饰符。
它可以结合过滤逻辑和用户建议项,快速构建直观的搜索体验。
与 SwiftUI 的状态驱动模式无缝集成。