建立搜尋功能、客製化搜尋列操作時相關設定,以及取消按鈕的文字和執行的事件。
流程
- 建立搜尋列 UISearchController
override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController()
}
2. 搜尋列位置:導覽列或表頭
navigationItem.searchController = searchController // 導覽列tableView.tableHeaderView = searchController.searchBar // 表頭
3. 實現搜尋功能
- 【搜尋結果】
宣告新變數用以儲存篩選後的資料內容,tableView 以新變數來顯示內容
lazy var filteredSongs = songs // 新變數
- 【搜尋功能 protocol:UISearchResultsUpdating 】
- 委派:將 controller 設為 UISearchController 的 searchResultsUpdater
searchController.searchResultsUpdater = self
- 遵從:UISearchResultsUpdating 的 protocol
- 定義:updateSearchResults function:依據搜尋文字調整資料且呼叫 tableView的 reloadDate 更新顯示表格內容
// MARK: UISearchResultsUpdating - search controller 更新表格內容
extension AddWorldClockTableViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text,
searchText.isEmpty == false {
filteredZoneList = zoneList.filter({($0.cityNameByCN+$0.countryNameByCN).localizedStandardContains(searchText)})
} else {
filteredZoneList = zoneList
}
tableView.reloadData()
}
}
補充
【固定搜尋列於上方】:畫面捲動時不隱藏搜尋列
// 畫面捲動 search bar 不隱藏 navigationItem.hidesSearchBarWhenScrolling = false
【搜尋時導覽列不隱藏】
p.s. 預設為 true,當搜尋時導覽列則隱藏
searchController.hidesNavigationBarDuringPresentation = false
【取消按鈕】
- 固定顯示取消按鈕
p.s. 預設為 false,只有搜尋文字不為空白字串才會顯示「取消」
searchController.searchBar.showsCancelButton = true
- 取消按鈕標題文字
p.s. 預設為 Cancel
if let cancelButton = searchController.searchBar.value(forKey: "cancelButton") as? UIButton {
cancelButton.setTitle("取消", for: .normal)
}
- 客製化執行取消按鈕的事件 protocol:
UISearchBarDelegate
p.s. 預設為點選取消則取消搜尋
- 委派:searchController.searchBar.delegate = self
- 遵從:UISearchBarDelegate
- 定義:searchBarCancelButtonClicked
➪ 實作:按下取消按鈕後退出畫面
// MARK: UISearchBarDelegate - search bar 取消觸發
extension AddWorldClockTableViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar){
dismiss(animated: true, completion: nil)
}
}
【完整程式碼】
let zoneList = Zone.data
lazy var filteredZoneList = zoneList // 搜尋結果override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self // 實作搜尋
tableView.tableHeaderView = searchController.searchBar // 搜尋列位置:表頭
navigationItem.searchController = searchController // 搜尋列位置:導覽列
navigationItem.hidesSearchBarWhenScrolling = false // 畫面捲動 search bar 不隱藏
searchController.hidesNavigationBarDuringPresentation = false //搜尋時是否隱藏導覽列
// 取消按鈕
searchController.searchBar.delegate = self // 實作取消
searchController.automaticallyShowsCancelButton = false // 不顯示取消按鈕;預設為true,點選search bar才顯示
searchController.searchBar.showsCancelButton = true // 取消按鈕一直顯示;預設為 false
if let cancelButton = searchController.searchBar.value(forKey: "cancelButton") as? UIButton {
cancelButton.setTitle("取消", for: .normal)
}
}// MARK: UISearchResultsUpdating - search controller 更新表格內容
extension AddWorldClockTableViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
if let searchText = searchController.searchBar.text,
searchText.isEmpty == false {
filteredZoneList = zoneList.filter({($0.cityNameByCN+$0.countryNameByCN).localizedStandardContains(searchText)})
} else {
filteredZoneList = zoneList
}
tableView.reloadData()
}
}// MARK: UISearchBarDelegate - search bar 取消觸發
extension AddWorldClockTableViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar){
delegate?.addWorldClockTableViewControllerDidCancel(self)
dismiss(animated: true, completion: nil)
}
}
實作:仿時鐘 App 的世界時鐘分頁搜尋時區
畫面刻畫和時區參考 GitHub