UISearchController学习

效果

UISearchController学习_第1张图片
效果演示.gif

为什么写

看微信搜索的的界面,一直好奇点击搜索框之后的动画怎么弄的。在很多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后才有的属性.
obscuresBackgroundDuringPresentationdimsBackgroundDuringPresentation行为相同
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 直接从他的代码里复制的

你可能感兴趣的:(UISearchController学习)