在 iOS 15 推出之前,SwiftUI 並沒有內置修飾符來在 List
視圖中處理搜尋,開發者需要創建自己的解決方案。我們還寫了一篇教學文章,教大家利用 TextField
來打造一個搜尋欄 (search bar),並顯示搜尋結果。在 iOS 15 推出之後,SwiftUI 框架為 List
視圖帶來了一個名為 searchable
的新修飾符 (modifier)。
在這篇教學文章中,我們會探討這個修飾符,看看為一個 List 實作搜尋有多簡單!
Searchable 的基本使用
假設你已經創建了一個 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 標題下。
在預設情況下,它會顯示 Search 為佔位符 (placeholder)。如果想更改它,你可以如此編寫 .searchable
修飾符,並設置自己的佔位符。
.searchable("Search articles...", text: $searchText)
搜尋欄的位置
.searchable
修飾符有一個 placement
參數 (parameter),用於指定搜尋欄的位置。在預設情況下,它會設置為 .automatic
。在 iPhone 上,搜尋欄位於 Navigation Bar 標題的下方。當我們向上滾動 List 視圖時,搜尋欄就會被隱藏。
如果想像上面這樣長期顯示搜尋欄,我們可以更改 .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 上。
如果我們想將搜尋欄放在 detail 視圖中呢?我們可以將 .searchable
修飾符附加到範例程式碼的 Text
視圖中。
Text("Article Content")
.searchable(text: $searchText)
iPadOS 就會在 detail 視圖的右上角顯示搜尋欄。
同樣,我們可以調整 placement
參數的值,來更改搜尋欄的位置。看看以下例子:
.searchable(text: $searchText, placement: .navigationBarDrawer)
如果我們把 placement
參數設置為 .navigationBarDrawer
,iPadOS 就會將搜尋欄放置在 Navigation Bar 標題的下方。
執行搜尋並顯示搜尋結果
我們有很多種方法可以過濾 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")
}
以上的程式碼會顯示搜尋建議,當中有兩個可點擊的搜尋字詞。使用者可以輸入搜尋關鍵字,或是點擊搜尋建議來執行搜尋。
總結
iOS 15 為 SwiftUI 框架帶來了另一個備受期待的功能。.searchable
修飾符簡化了實作搜尋欄的步驟,並讓我們不需要創建解決方案,為我們節省了時間。唯一的缺點是這個功能僅適用於 iOS 15(或更新版本)。如果你正在構建需要支持舊版本 iOS 的 App,就還是需要構建自己的搜尋欄。
原文:How to Implement Search for SwiftUI List Using Searchable