第 37 章
利用 Searchable 建立搜尋欄
在 iOS 15 之前,SwiftUI 沒有內置修飾器在List視圖中加入搜尋功能。開發者必須建立自己的解決方案。 在前面的章節中,我已經介紹了兩個自建搜尋欄的方法。隨著 iOS 15 推出,SwiftUI 框架為 List 視圖帶來了一個名為
searchable
的新修飾器,讓你更輕易建立搜尋欄。
在本章中,你將學習使用searchable
,待會你就會受到這個修飾器有多方便。
Searchable 的基本用法
為了講解 Searchable
的用法,請從以下網址下載範例項目:https://www.appcoda.com/resources/swiftui4/SwiftUISearchableStarter.zip.
範例的初始項目已經準備好了一個列表視圖來顯示一組文章。 之後,我們會加入一個用於過濾文章的搜尋欄。 要將搜尋欄添加到列表視圖,你需要做的就是宣告一個狀態變數(例如searchText
)來存放搜尋文字並將searchable
修飾器附加到NavigationStack
,如下所示:
struct ContentView: View {
@State var articles = sampleArticles
@State private var searchText = ""
var body: some View {
NavigationStack {
.
.
.
}
.searchable(text: $searchText)
}
}
SwiftUI 會自動為你加入搜尋欄,並將其放在導航欄標題下方。 如果找不到搜尋欄,請嘗試執行App並向下拖動列表視圖。 這樣搜尋框就應該出現。
在預設情況下,它顯示 Search 作為佔位符。 如果你想更改它,你可以像這樣編寫.searchable
修飾器並使用你指定的佔位符:
.searchable(text: $searchText, prompt: "Search articles...")
搜尋欄位置
.searchable
修飾器有一個 placement
參數,用於指定搜尋欄的位置。 在預設的情況下,它設置為.automatic
。 就 iPhone 而言,搜尋欄會顯示於導航欄標題下方。 當你向上滾動列表視圖時,搜尋欄就會自動隱藏。
如果想永久顯示搜尋欄,可以更改 .searchable
修飾器並提供 placement
參數,如下所示:
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
到目前為止,我們將 .searchable
修飾器附加到導航視圖。 你實際上可以將它附加到 List
視圖並在 iPhone 上實現相同的結果。
話雖如此,在 iPadOS 上使用 split view 時,.searchable
修飾器的擺放位置會直接影響搜尋欄的顯示位置。 再看一下範例程式碼:
NavigationSplitView {
List {
ForEach(articles) { article in
ArticleRow(article: article)
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
.navigationTitle("AppCoda")
} detail: {
Text("Article details")
}
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
像往常一樣,我們將 .searchable
修飾器附加到導航視圖。 如果你在 iPad 上運行範例App,搜尋欄會顯示在拆分視圖的側邊欄上。
如果你想將搜尋欄放在詳細視圖中,那應怎樣做? 你可以嘗試在 .navigationTitle
修飾器的正上方加入以下程式碼:
Text("Article details")
.searchable(text: $searchText)
這樣,iPadOS 將在詳細視圖的右上角顯示一個額外的搜尋欄。
同樣地,你可以通過調整 placement
參數的值來進一步更改搜尋欄的位置。 這是一個例子:
.searchable(text: $searchText, placement: .navigationBarDrawer)
通過將 placement
參數設置為 .navigationBarDrawer
,iPadOS 就會將搜尋欄置於導航欄標題下方。
如何執行搜尋並顯示搜索結果
搜尋數據的方法有很多種。 你可以建立一個計算屬性(computed property)來實時過濾數據。 又或者,你可以附加 .onChange
修飾器以監測使用者輸入的搜尋文字,如有更改就立刻啟動搜尋。 試試更新 NavigationStack
的程式碼,如下所示:
NavigationStack {
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
}
}
每當使用者輸入搜尋字時,App都會執行 .onChange
修飾器。 然後我們使用 filter
方法實時進行搜尋。Xcode 預覽無法正常搜索,請在模擬器上測試搜索功能。
添加搜尋建議
.searchable
修飾器允許你添加搜尋建議列表,以顯示一些常用的搜索詞或搜尋歷史。 例如,你可以像這樣建立可點擊的搜尋建議:
.searchable(text: $searchText) {
Text("SwiftUI").searchCompletion("SwiftUI")
Text("iOS 15").searchCompletion("iOS 15")
}
當使用者進行搜索時,搜尋欄就會顯示兩個常用的搜尋建議。 使用者可以鍵入搜尋關鍵字或點擊搜尋建議來執行搜索。
在 iOS 16 上,Apple 引入了一個名為 .searchSuggestions
的修飾符,用於添加搜索建議。 以上同一段程式碼可以寫成這樣:
.searchable(text: $searchText)
.searchSuggestions {
Text("SwiftUI").searchCompletion("SwiftUI")
Text("iOS 15").searchCompletion("iOS 15")
}
總結
.searchable
修飾器簡化了搜尋欄的實作方法。在一般情況下,我們不再需要自己開發搜尋欄。 缺點是此功能僅適用於 iOS 15(或更高版本)。 如果你正在構建一個需要支持舊版本 iOS 的應用程序,你仍然需要建立自己的搜尋欄。
想更深入學習SwiftUI和下載完整程式碼?你可以從 AppCoda網站購買《精通 SwiftUI》完整電子版。