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。
我们可以调用类似于函数调用的闭包。

