效果
为什么写
看微信搜索的的界面,一直好奇点击搜索框之后的动画怎么弄的。在很多app都看到过,以前自己实现并没有这么实现。今天正好有空 && 正好又想起来了,就去了解了一下
UISearchController文档
// Pass nil if you wish to display search results in the same view that you are searching. This is not supported on tvOS; please provide a results controller on tvOS.
public init(searchResultsController: UIViewController?)
初始化UISearchController时可以给它一个结果显示控制器,也就是结果会在新的view上显示。比如上面的演示的gif,点击搜索之后出现了一个新view,搜索结果显示在新的view。
当然,searchResultsController也可以是nil。那么搜索结果会显示当前view上。
使用情况:
对于在一个列表里搜索特定条件的内容,例如在歌单里搜索某首歌,这里新的结果并不需要新的显示方式,这里就是适合将searchResultsController置为nil
对于搜索结果呈现多种样式的,显然需要给一个新的searchResultsController。这样我们可以定义与原界面不同的显示方式。
// The object responsible for updating the content of the searchResultsController.
weak public var searchResultsUpdater: UISearchResultsUpdating?
searchResultsUpdater
属性,用于更新搜索结果。必须服从UISearchResultsUpdating
协议
然后在func searchBar(searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int)
协议方法里对所有结果进行处理
// Setting this property to YES is a convenience method that performs a default presentation of the search controller appropriate for how the controller is configured. Implement -presentSearchController: if the default presentation is not adequate.
public var active: Bool
active
属性就是当前 searchController
是不是处于激活状态.只要点击 searchBar
,active
就会被置为 true.
我们利用这个属性对显示数据进行选择
weak public var delegate: UISearchControllerDelegate?
代理方法.具体有哪些代理方法这里就不细说.
public var dimsBackgroundDuringPresentation: Bool // default is YES, and has the same behavior as obscuresBackgroundDuringPresentation.
默认情况下,UISearchController
暗化前一个view,这在我们使用另一个view controller来显示结果时非常有用.演示 gif 就做了暗化
// You are free to become the search bar's delegate to monitor for text changes and button presses.
public var searchBar: UISearchBar { get }
searchBar
这是一个大的模块.请自己研究.例子中用到scopeButtonTitles
属性
@available(iOS 9.1, *)
public var obscuresBackgroundDuringPresentation: Bool // default is YES
public var hidesNavigationBarDuringPresentation: Bool // default is YES
两个9.1后才有的属性.
obscuresBackgroundDuringPresentation
与dimsBackgroundDuringPresentation
行为相同
hidesNavigationBarDuringPresentation
隐藏navigationBar
,这就是我们看到的动画效果
demo解析
// MARK: - properties - 即定义的各种属性
var tableView: UITableView! // tableView
var dataSource = [
Candy(category:"Chocolate", name:"Chocolate Bar"),
Candy(category:"Chocolate", name:"Chocolate Chip"),
Candy(category:"Chocolate", name:"Dark Chocolate"),
Candy(category:"Hard", name:"Lollipop"),
Candy(category:"Hard", name:"Candy Cane"),
Candy(category:"Hard", name:"Jaw Breaker"),
Candy(category:"Other", name:"Caramel"),
Candy(category:"Other", name:"Sour Chew"),
Candy(category:"Other", name:"Gummi Bear")
]
var searchController: UISearchController! // 搜索vc
var searchResultsController: UITableViewController! // 搜索结果vc
var searchResults:Array = [Candy]() //搜索结果
创建tableView 和 searchController
func setUpTableView() {
tableView = UITableView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height), style: UITableViewStyle.Plain)
tableView.backgroundColor = UIColor.whiteColor()
tableView.dataSource = self
tableView.delegate = self
tableView.contentOffset = CGPointMake(0,44)
view.addSubview(tableView)
}
func setupSearchController (){
searchResultsController = UITableViewController(style: .Plain)
searchResultsController.tableView.delegate = self
searchResultsController.tableView.dataSource = self
// searchResultsController.tableView.rowHeight = 63
searchResultsController.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "LogCell")
searchController = UISearchController(searchResultsController: searchResultsController)
searchController.searchResultsUpdater = self
searchController.searchBar.sizeToFit()
searchController.searchBar.delegate = self
searchController.searchBar.barTintColor = UIColor(red: 0, green: 104.0/255.0, blue: 55.0/255.0, alpha: 1.0)
tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true // 保证在UISearchController在激活状态下用户push到下一个view controller之后search bar不会仍留在界面上
searchController.searchBar.scopeButtonTitles = ["All", "Chocolate", "Hard", "Other"] // segment control
searchController.searchBar.delegate = self
}
UITableView 代理
// UITableViewDelegate && UITableViewDataSource
extension ViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searchController.active {
return searchResults.count
}else{
return dataSource.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell!
// 切换不同的 cell
if searchController.active && searchController.searchBar.text != "" {
cell = tableView.dequeueReusableCellWithIdentifier("Logcell")
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Logcell")
}
}else{
cell = tableView.dequeueReusableCellWithIdentifier("cell")
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
}
}
// 切换不同的数据
let candy:Candy
if searchController.active {
candy = searchResults[indexPath.row]
}else{
candy = dataSource[indexPath.row]
}
cell.textLabel?.text = candy.name
cell.detailTextLabel?.text = candy.category
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let title: String!
if searchController.active{
title = searchResults[indexPath.row].name
}else{
title = dataSource[indexPath.row].name
}
let detailVC = RNDetailViewController()
detailVC.myTitle = title
navigationController?.pushViewController(detailVC, animated: true)
}
}
** UISearchResultsUpdating代理**
// UISearchResultsUpdating
// 更新搜索结果
func updateSearchResultsForSearchController(searchController: UISearchController) {
let searchBar = searchController.searchBar
let scope = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex]
filterResultsWithSearchString(searchController.searchBar.text!, scope: scope)
}
** UISearchBarDelegate**
// UISearchBarDelegate
extension ViewController: UISearchBarDelegate{
// 点击ScopeButton执行方法
func searchBar(searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
filterResultsWithSearchString(searchBar.text!, scope: searchBar.scopeButtonTitles![selectedScope])
}
}
** 搜索数据**
// 搜索数据
func filterResultsWithSearchString(searchString: String, scope: String = "All"){
searchResults = dataSource.filter { candy in
let categoryMatch = (scope == "All") || (candy.category == scope)
return categoryMatch && candy.name.lowercaseString.containsString(searchString.lowercaseString )
}
searchResultsController.tableView.reloadData()
}
源代码地址
RNSearchControllerDemo
总结
只是基本了解了一下UISearchController
,还有很多需要挖掘.
demo 里面主要是有searchResultsController
的情况.
感谢 Xiao_Li 的文章.
- 我的dataSource 直接从他的代码里复制的