这篇文章介绍了SwiftUI的searchable()修饰符,iOS 16引入的功能允许添加搜索栏,并在iOS 17中作了改进,如支持NavigationStack、监控搜索活动状态及自定义搜索范围,增强搜索体验。
此内容根据文章生成,并经过人工审核,仅用于文章内容的解释与总结
投诉 在iOS 16的更新中,SwiftUI为开发者们带来了一个新的功能——searchable()
修饰符。这个修饰符允许我们直接在NavigationView
中放置一个搜索栏。在简单的布局中,这个搜索栏保持固定位置;而当与列表一起使用时,它会自动出现并随着列表的滚动而滚动。
最简单的使用方法是在导航视图内的某个视图上添加searchable()
,就像这样:
Text 1 2 3 4 5 6 7 8 9 10 11 struct ContentView: View { @State private var searchText = "" var body: some View { NavigationView { Text("Searching for \(searchText)") .searchable(text: $searchText) .navigationTitle("Searchable Example") } } }
此外,你还可以为搜索框提供一个提示字符串,如下所示:
Text 1 2 3 4 5 6 7 8 9 10 11 struct ContentView: View { @State private var searchText = "" var body: some View { NavigationView { Text("Searching for \(searchText)") .searchable(text: $searchText, prompt: "Look for something") .navigationTitle("Searchable Example") } } }
然而,在实际应用中,你更可能使用它来过滤一个数据列表,例如这样:
Text 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 struct ContentView: View { let names = ["Holly", "Josh", "Rhonda", "Ted"] @State private var searchText = "" var body: some View { NavigationView { List { ForEach(searchResults, id: \.self) { name in NavigationLink(destination: Text(name)) { Text(name) } } } .searchable(text: $searchText) .navigationTitle("Contacts") } } var searchResults: [String] { if searchText.isEmpty { return names } else { return names.filter { $0.contains(searchText) } } } }
当搜索栏出现在列表中时,它通常是隐藏的——用户需要轻轻向下拉列表的顶部才能显示出来。
对于更高级的用法,searchable()
允许我们向用户显示一系列建议,甚至添加额外的完成信息以减少他们的输入量。这是通过向searchable()
传递一个返回包含建议的视图的函数来实现的。如果你希望用户能够点击完成他们的搜索,请为每个建议使用searchCompletion()
修饰符。
因此,我们可以修改前面的示例,提供用户输入时可点击的建议,而不是仅在原地过滤整个列表:
Text 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 struct ContentView: View { let names = ["Holly", "Josh", "Rhonda", "Ted"] @State private var searchText = "" var body: some View { NavigationView { List { ForEach(searchResults, id: \.self) { name in NavigationLink(destination: Text(name)) { Text(name) } } } .searchable(text: $searchText) { ForEach(searchResults, id: \.self) { result in Text("Are you looking for \(result)?").searchCompletion(result) } } .navigationTitle("Contacts") } } var searchResults: [String] { if searchText.isEmpty { return names } else { return names.filter { $0.contains(searchText) } } } }
这样,“Are you looking for Holly?”和类似的建议就可以在屏幕上显示出来。同时,每个人的名字都被用作完成提示,这意味着如果你输入“Ho”并点击“Holly”,搜索栏将自动完成为全名。
对于更高级的搜索,你可以为搜索框添加搜索范围 ,让用户选择他们想要的搜索类型。例如,我们可以编写一些代码,让用户在搜索他们的收件箱或仅搜索他们的收藏消息之间进行选择,如下所示:
Text 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 struct Message: Identifiable, Codable { let id: Int var user: String var text: String } enum SearchScope: String, CaseIterable { case inbox, favorites } struct ContentView: View { @State private var messages = [Message]() @State private var searchText = "" @State private var searchScope = SearchScope.inbox var body: some View { NavigationView { List { ForEach(filteredMessages) { message in VStack(alignment: .leading) { Text(message.user) .font(.headline) Text(message.text) } } } .searchable(text: $searchText, scope: $searchScope) { ForEach(SearchScope.allCases, id: \.self) { scope in Text(scope.rawValue.capitalized) } } .navigationTitle("Messages") } .onSubmit(of: .search, runSearch) .onChange(of: searchScope) { _ in runSearch() } } var filteredMessages: [Message] { if searchText.isEmpty { return messages } else { return messages.filter { $0.text.localizedCaseInsensitiveContains(searchText) } } } func runSearch() { Task { guard let url = URL(string: "https://hws.dev/\(searchScope.rawValue).json") else { return } let (data, _) = try await URLSession.shared.data(from: url) messages = try JSONDecoder().decode([Message].self, from: data) } } }
以上代码展示了如何在SwiftUI中使用searchable()
修饰符来创建更动态和交互性更强的搜索体验。通过添加搜索范围和过滤条件,开发者可以提供更精准和个性化的搜索功能,从而提升用户体验。这些功能的引入,无疑使SwiftUI成为一个更加强大和灵活的UI框架,进一步推动了其在现代iOS应用开发中的应用。
iOS 17版本在searchable有一些变化,在讨论iOS 17中SwiftUI的searchable()
修饰符的更新时,我们可以注意到几个关键区别与新增功能,相比于iOS 16版本。下面我将逐一解释这些变化,并为每个变化提供一个示例:
引入NavigationStack
的支持 :
iOS 16 :searchable()
修饰符主要用于NavigationView
。
iOS 17 :searchable()
现在支持用于NavigationStack
。
示例 :在iOS 17中,你可以将searchable()
直接应用于NavigationStack
中的视图。
1 2 3 4 5 6 7 8 9 10 struct ContentView : View { @State private var searchText = "" var body: some View { NavigationStack { Text ("Searching for \(searchText) " ) .searchable(text: $searchText ) } } }
监控搜索活动状态 :
iOS 17 新增:可以绑定一个布尔值来监控搜索栏是否正在显示。
示例 :在iOS 17中,使用isPresented
绑定来监控搜索栏的显示状态。
1 2 3 4 5 6 7 8 9 10 11 struct ContentView : View { @State private var searchText = "" @State private var searchIsActive = false var body: some View { NavigationStack { Text ("Searching for \(searchText) " ) .searchable(text: $searchText , isPresented: $searchIsActive ) } } }
搜索范围的定制化 :
iOS 17 新增:通过searchScopes()
修饰符来控制搜索的范围。
示例 :在iOS 17中,使用searchScopes()
允许用户选择搜索的特定范围。
1 2 3 4 5 6 7 8 9 10 11 12 struct ContentView : View { @State private var searchText = "" @State private var searchScope = SearchScope .inbox var body: some View { NavigationStack { List { } .searchable(text: $searchText ) .searchScopes($searchScope ) { } } } }
这些改变展示了SwiftUI的逐步进化,以及苹果如何不断增强和完善其框架来提供更灵活、更强大的开发工具。通过这些更新,开发者能够为用户提供更丰富和便利的搜索体验。
参考网站 How to add a search bar to filter your data
张洪Heo
分享设计与科技生活
本文是转载或翻译文章,版权归原作者所有。建议访问原文,转载本文请联系原作者。