在 iOS 15 推出之前,SwiftUI 並沒有內置修飾符來在 List
視圖中處理搜尋,開發者需要創建自己的解決方案。我們還寫了一篇教學文章,教大家利用 TextField
來打造一個搜尋欄 (search bar),並顯示搜尋結果。在 iOS 15 推出之後,SwiftUI 框架為 List
視圖帶來了一個名為 searchable
的新修飾符 (modifier)。
在這篇教學文章中,我們會探討這個修飾符,看看為一個 List 實作搜尋有多簡單!
Searchable 的基本使用
![Search-bar-ios15-demo](https://www.appcoda.com/wp-content/uploads/2021/06/swiftui-searchable-demo.png)
假設你已經創建了一個 List 視圖來顯示一系列文章,並希望提供一個搜尋欄來過濾文章。要將搜尋欄添加到 List 視圖,我們只需要宣告一個狀態變數 (state variable),來保存搜尋文本 (search text),並附加 searchable
修飾符到 NavigationView
即可:
struct SearchListView: View {
@State var articles = sampleArticles
@State private var searchText = ""
var body: some View {
NavigationView {
.
.
.
}
.searchable(text: $searchText)
}
}
SwiftUI 會自動幫我們呈現搜尋欄,並將其放在 Navigation Bar 標題下。
![swiftui-searchable-search-bar](https://www.appcoda.com/wp-content/uploads/2021/06/swiftui-searchable-search-bar.png)
在預設情況下,它會顯示 Search 為佔位符 (placeholder)。如果想更改它,你可以如此編寫 .searchable
修飾符,並設置自己的佔位符。
.searchable("Search articles...", text: $searchText)
搜尋欄的位置
.searchable
修飾符有一個 placement
參數 (parameter),用於指定搜尋欄的位置。在預設情況下,它會設置為 .automatic
。在 iPhone 上,搜尋欄位於 Navigation Bar 標題的下方。當我們向上滾動 List 視圖時,搜尋欄就會被隱藏。
![searchable-permanent-search-bar-placement](https://www.appcoda.com/wp-content/uploads/2021/06/swiftui-searchable-permanent-searchbar.png)
如果想像上面這樣長期顯示搜尋欄,我們可以更改 .searchable
修飾符,並如此指定 placement
參數:
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
我們一直都將 .searchable
修飾符附加到 Navigation 視圖,其實我們也可以將它附加到 List
視圖,這樣在 iPhone 上都可以達到相同的效果。
不過,在 iPad OS 上使用 Splitview 時,.searchable
修飾符的位置就會影響搜尋欄的位置。讓我們看看下面的範例程式碼:
NavigationView {
List {
ForEach(articles) { article in
ArticleRow(article: article)
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
Text("Article Content")
.navigationTitle("AppCoda")
}
.searchable(text: $searchText)
平常我們將 .searchable
修飾符附加到 Navigation 視圖中,在這種情況下,搜尋欄會顯示在 Split 視圖的 sidebar 上。
![searchable-on-ipados](https://www.appcoda.com/wp-content/uploads/2021/06/swiftui-searchable-ipados.png)
如果我們想將搜尋欄放在 detail 視圖中呢?我們可以將 .searchable
修飾符附加到範例程式碼的 Text
視圖中。
Text("Article Content")
.searchable(text: $searchText)
iPadOS 就會在 detail 視圖的右上角顯示搜尋欄。
![searchable-ipados-search-bar](https://www.appcoda.com/wp-content/uploads/2021/06/swiftui-searchable-ipados-detail-view.png)
同樣,我們可以調整 placement
參數的值,來更改搜尋欄的位置。看看以下例子:
.searchable(text: $searchText, placement: .navigationBarDrawer)
如果我們把 placement
參數設置為 .navigationBarDrawer
,iPadOS 就會將搜尋欄放置在 Navigation Bar 標題的下方。
![searchable-ipados-navigationbardrawer](https://www.appcoda.com/wp-content/uploads/2021/06/swiftui-searchable-ipados-navigationbardrawer.png)
執行搜尋並顯示搜尋結果
![searchable-perform-search](https://www.appcoda.com/wp-content/uploads/2021/06/swiftui-searchable-search.png)
我們有很多種方法可以過濾 Data List。我們可以創建一個實時執行資料過濾的計算屬性;或是附加 .onChange
修飾符,以追踪搜尋欄的改變。每當使用者在搜尋欄輸入內容時,就會實時執行搜尋。看看以下的範例程式碼片段:
NavigationView {
List {
ForEach(articles) { article in
ArticleRow(article: article)
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
.navigationTitle("AppCoda")
}
.searchable(text: $searchText)
.onChange(of: searchText) { searchText in
if !searchText.isEmpty {
articles = sampleArticles.filter { $0.title.contains(searchText) }
} else {
articles = sampleArticles
}
}
添加搜尋建議
我們可以利用 .searchable
修飾符來添加搜尋建議列表,以顯示一些常用的搜尋字詞或搜尋歷史。舉個例子,你可以這樣創建可點擊 (tappable) 的搜索建議:
.searchable(text: $searchText) {
Text("SwiftUI").searchCompletion("SwiftUI")
Text("iOS 15").searchCompletion("iOS 15")
}
以上的程式碼會顯示搜尋建議,當中有兩個可點擊的搜尋字詞。使用者可以輸入搜尋關鍵字,或是點擊搜尋建議來執行搜尋。
![searchable-swiftui-perform-search](https://www.appcoda.com/wp-content/uploads/2021/06/swiftui-searchable-search-suggestion.png)
總結
iOS 15 為 SwiftUI 框架帶來了另一個備受期待的功能。.searchable
修飾符簡化了實作搜尋欄的步驟,並讓我們不需要創建解決方案,為我們節省了時間。唯一的缺點是這個功能僅適用於 iOS 15(或更新版本)。如果你正在構建需要支持舊版本 iOS 的 App,就還是需要構建自己的搜尋欄。
原文:How to Implement Search for SwiftUI List Using Searchable