iOS UISearchController和UITableView
在本教程中,我们将开发一个应用程序,该应用程序使用UISearchController在TableView上实现搜索功能。
我们在此处的Android教程中做了类似的操作。
UISearchController
UISearchController包含协议" UISearchResultsUpdating",每当UISearchBar中的文本发生更改时,该协议就会通过下面提供的函数通知ViewController类。
func updateSearchResults(for searchController:UISearchController)
在以下应用程序中,我们将使用TableViewController作为默认的视图控制器类型,并以编程方式在其顶部添加一个UISearchController(UISearchController在Interface Builder中不可用)。
我们将使用Subtitle样式的TableViewCell,它在每行中包含一个标题和一个描述,并将使用Model类填充该描述。
iOS UISearchController示例项目结构
UISearchController示例代码
创建一个新文件" Model.swift",该文件存储每一行的数据。
import Foundation struct Model { let movie : String let genre : String }
下面给出了ViewController.swift源代码。
import UIKit class ViewController: UITableViewController { var models = [Model]() var filteredModels = [Model]() let searchController = UISearchController(searchResultsController: nil) override func viewDidLoad() { super.viewDidLoad() //Do any additional setup after loading the view, typically from a nib. self.tableView.tableFooterView = UIView() setupSearchController() models = [ Model(movie:"The Dark Night", genre:"Action"), Model(movie:"The Avengers", genre:"Action"), Model(movie:"Logan", genre:"Action"), Model(movie:"Shutter Island", genre:"Thriller"), Model(movie:"Inception", genre:"Thriller"), Model(movie:"Titanic", genre:"Romance"), Model(movie:"La la Land", genre:"Romance"), Model(movie:"Gone with the Wind", genre:"Romance"), Model(movie:"Godfather", genre:"Drama"), Model(movie:"Moonlight", genre:"Drama") ] } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() //Dispose of any resources that can be recreated. } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) let model: Model if searchController.isActive && searchController.searchBar.text != "" { model = filteredModels[indexPath.row] } else { model = models[indexPath.row] } cell.textLabel!.text = model.movie cell.detailTextLabel!.text = model.genre return cell } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if searchController.isActive && searchController.searchBar.text != "" { return filteredModels.count } return models.count } override func numberOfSections(in tableView: UITableView) -> Int { return 1 } func setupSearchController() { definesPresentationContext = true searchController.dimsBackgroundDuringPresentation = false searchController.searchResultsUpdater = self searchController.searchBar.barTintColor = UIColor(white: 0.9, alpha: 0.9) searchController.searchBar.placeholder = "Search by movie name or genre" searchController.hidesNavigationBarDuringPresentation = false tableView.tableHeaderView = searchController.searchBar } func filterRowsForSearchedText(_ searchText: String) { filteredModels = models.filter({( model : Model) -> Bool in return model.movie.lowercased().contains(searchText.lowercased())||model.genre.lowercased().contains(searchText.lowercased()) }) tableView.reloadData() } } extension ViewController: UISearchResultsUpdating { func updateSearchResults(for searchController: UISearchController) { if let term = searchController.searchBar.text { filterRowsForSearchedText(term) } } }
ew!那是一个很大的代码。
让我们逐步了解这一点。
ViewController类实现UITableViewController。
因此,无需分别实现Delegate和DataSource协议models数组将包含所有行的数据。
根据我们要设置的条件,filteredModels数组将包含与搜索到的字词匹配的行的数据初始化UISearchController的行是:
通过将" searchResultsController"设置为nil,我们声明搜索结果将在当前TableViewController本身而不是其他View中更新。为了摆脱空行,我们称之为:
让我们在SearchController上设置一些功能。
通过将definePresentationContext设置为true,我们确保将搜索控制器显示在原始表视图控制器的范围内。
" searchResultsUpdater"符合" UISearchResultsUpdating"协议。
设置此选项可确保每次searchBar中的文本更改时,都会调用扩展中存在的updateSearchResults函数。如果searchBar是否包含某些文本,则TableView的cellForRowAt和numberOfRowsInSection会显示过滤的模型或者模型类中的相关数据。
每次在方法updateSearchResults中更改文本时,都会调用filerRowsForSearchedText函数。
在上面的函数中,我们过滤了"模型"数组,仅将那些元素复制到"过滤的模型"中,该模型是"模型.movie"或者"模型.genre"类的子字符串。
- 在上面的代码中,filter方法内部的部分具有不同的语法。
称为"关闭"。
filter()采用类型为(model:Model)-> Bool的闭包,并遍历整个数组,仅返回与条件匹配的那些元素。
什么是封包?
闭包是一种没有关键字" func"的匿名函数。
" in"关键字用于将输入参数与返回部分分开。
闭包的示例是:
let searchController = UISearchController(searchResultsController: nil)
输入参数为Int,后跟->,返回类型再次为Int。
我们可以调用类似于函数调用的闭包。