翻译:luowanglin
原文地址
概览
这个Demo演示了表视图控制器(UITableViewController)和搜索控制器(UISearchController),怎样去创建一个管理和展示搜索内容的用户交互功能。通过创建一个自定义的表视图控制器,同时这个表示图控制器也充当展示或搜索结果的内容提供器,然后展示搜索内容范围内的过滤结果。
这个Demo实现了可选的UIStateRestoring接口协议,官方推介实现该接口协议。当app重启动时,可以通过视图控制器类去保存搜索栏的活动状态,其中包括第一响应状态和搜索栏文本,可进行数据的恢复。间接提升了更好的用户体验。
override func viewDidLoad() {
super.viewDidLoad()
resultsTableController = ResultsTableController()
resultsTableController.tableView.delegate = self
searchController = UISearchController(searchResultsController: resultsTableController)
searchController.searchResultsUpdater = self
searchController.searchBar.autocapitalizationType = .none
if #available(iOS 11.0, *) {
// For iOS 11 and later, place the search bar in the navigation bar.
navigationItem.searchController = searchController
// Make the search bar always visible.
navigationItem.hidesSearchBarWhenScrolling = false
} else {
// For iOS 10 and earlier, place the search controller's search bar in the table view's header.
tableView.tableHeaderView = searchController.searchBar
}
searchController.delegate = self
searchController.dimsBackgroundDuringPresentation = false // The default is true.
searchController.searchBar.delegate = self // Monitor when the search button is tapped.
/** Search presents a view controller by applying normal view controller presentation semantics.
This means that the presentation moves up the view controller hierarchy until it finds the root
view controller or one that defines a presentation context.
*/
/** Specify that this view controller determines how the search controller is presented.
The search controller should be presented modally and match the physical size of this view controller.
*/
definesPresentationContext = true
}
创建一个搜索控制器
使用继承至UITableViewController的MainTableViewController类去创建一个搜索控制器。ResultsTableController表视图控制器用于展示搜索栏中过滤后的产品(Product)结果。
为了兼容iOS系统版本,MainTableViewController搜索控制器需要进行系统版本的判断,当系统版本小于或等于iOS10时,你可以通过替换tableview里面的header视图,而在iOS11后的版本,你可以直接替换视图控制器的导航栏(navigation bar)。
刷新搜索结果
这个例子使用了UISearchResultsUpdating协议以及谓语适配器NSComparisonPredicate,去过滤分组里可用的产品(product)搜索结果。谓语(NSComparisonPredicate)是一个正则匹配基类,通过相应谓语查询规则进行查询或过滤。搜索规则是基于搜索栏的使用类型,会结合产品名称、年份以及价格。
通过在裁截输入栏中关键字的开头和结尾预前进行搜索。然后搜索字符串通过NSComparisonPredicate类里的findMatches函数进行搜索结果返回。这个搜索结果以列表的方式返回。
func updateSearchResults(for searchController: UISearchController) {
// Update the filtered array based on the search text.
let searchResults = products
// Strip out all the leading and trailing spaces.
let whitespaceCharacterSet = CharacterSet.whitespaces
let strippedString =
searchController.searchBar.text!.trimmingCharacters(in: whitespaceCharacterSet)
let searchItems = strippedString.components(separatedBy: " ") as [String]
// Build all the "AND" expressions for each value in searchString.
let andMatchPredicates: [NSPredicate] = searchItems.map { searchString in
findMatches(searchString: searchString)
}
// Match up the fields of the Product object.
let finalCompoundPredicate =
NSCompoundPredicate(andPredicateWithSubpredicates: andMatchPredicates)
let filteredResults = searchResults.filter { finalCompoundPredicate.evaluate(with: $0) }
// Apply the filtered results to the search results table.
if let resultsController = searchController.searchResultsController as? ResultsTableController {
resultsController.filteredProducts = filteredResults
resultsController.tableView.reloadData()
}
}