iOS UISearchController和UITableView

In this tutorial, we’ll be developing an application that implements a search function over a TableView using UISearchController. We’ve done something similar in an Android Tutorial here.

在本教程中,我们将开发一个应用程序,该应用程序使用UISearchController在TableView上实现搜索功能。 我们在这里的Android教程中做了类似的事情。

UISearchController (UISearchController)

UISearchController contains a protocol UISearchResultsUpdating which informs our ViewController class through the function given below whenever text in the UISearchBar is changed.

UISearchController包含协议UISearchResultsUpdating它通过功能通知我们的ViewController类下面每当在文本的UISearchBar改变给出。

func updateSearchResults(for searchController: UISearchController)

func updateSearchResults(for searchController: UISearchController)

In the following application, we’ll use a TableViewController as the default view controller type and add a UISearchController at the top of it programmatically(UISearchController is not available in the Interface Builder). We’ll be using a TableViewCell of the style Subtitle which contains a title and a description in each row that would be populated using a Model class.

在以下应用程序中,我们将使用TableViewController作为默认的视图控制器类型,并以编程方式在其顶部添加一个UISearchController(UISearchController在Interface Builder中不可用)。 我们将使用Subtitle样式的TableViewCell,该样式在每行中包含一个标题和一个描述,并将使用Model类填充该描述。

iOS UISearchController示例项目结构 (iOS UISearchController Example Project Structure)

故事板 (Storyboard)

UISearchController示例代码 (UISearchController example code)

Create a new file Model.swift that stores the data for each row.

创建一个新文件Model.swift ,该文件存储每一行​​的数据。

import Foundation

struct Model {
    let movie : String
    let genre : String
}

The ViewController.swift source code is given below.

下面给出了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)
        }
    }
}

Pheww! That’s a big code. Let’s understand this step by step.

ew! 那是一个很大的代码。 让我们逐步了解这一点。

  1. The ViewController class implements UITableViewController. So there’s no need to implement the Delegate and DataSource protocols separately

    ViewController类实现UITableViewController。 因此,无需分别实现Delegate和DataSource协议
  2. The models array would contain the data for all the rows. The filteredModels array would contain the data for the rows that match the searched term based on the condition we’d be setting

    models数组将包含所有行的数据。 根据我们要设置的条件, filteredModels数组将包含与搜索到的术语匹配的行的数据
  3. The line that initialises the UISearchController is:
    let searchController = UISearchController(searchResultsController: nil)

    By setting the searchResultsController to nil we state that the search results would be updated in the current TableViewController itself rather than a different View.

    通过将searchResultsController设置为nil,我们声明将在当前TableViewController本身而不是其他View中更新搜索结果。

  4. To get rid of the empty rows we call:
    self.tableView.tableFooterView = UIView()

    为了摆脱空行,我们称之为:
    • Let’s setup a few features on the SearchController.
      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
          }

      By setting definesPresentationContext to true we ensure that the search controller is presented within the bounds of the original table view controller.

    • searchResultsUpdater conforms to the UISearchResultsUpdating protocol. Setting this makes sure that the updateSearchResults function present in the extension would be invoked everytime text in searchBar changes.

    • 让我们在SearchController上设置一些功能。

      通过将definePresentationContext设置为true,我们确保将搜索控制器显示在原始表视图控制器的范围内。

    • searchResultsUpdater符合UISearchResultsUpdating协议。 设置此选项可确保每次searchBar中的文本更改时,都会调用扩展中存在的updateSearchResults函数。
  1. The TableView cellForRowAt and numberOfRowsInSection display the relevant data from the filteredModels or models class if the searchBar has some text or not.

    如果searchBar是否包含某些文本,则TableView cellForRowAtnumberOfRowsInSection显示filteredModels或models类中的相关数据。
  2. The filerRowsForSearchedText function is invoked every time text changes inside the method updateSearchResults.

    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()
        }

    In the above function, we filtered the models array and copy only those elements into filteredModels which are a substring of the models.movie or models.genre class.

    filerRowsForSearchedText方法updateSearchResults文本更改时,都会调用filerRowsForSearchedText函数。

    在上面的函数,我们过滤models阵列和复制仅这些要素成filteredModels它们是的一个子models.moviemodels.genre类。

  3. In the above code, the part inside the filter method has a different syntax. It’s called a closure.
    {( model : Model) -> Bool in
                return model.movie.lowercased().contains(searchText.lowercased())||model.genre.lowercased().contains(searchText.lowercased())
            }

    filter() takes a closure of type (model: Model) -> Bool and iterates over the entire array, returning only those elements that match the condition.

    closure

    filter()采用类型为(model: Model) -> Bool的闭包,并遍历整个数组,仅返回与条件匹配的那些元素。

什么是封包? (What are closures?)

Closures are sort of anonymous functions without the keyword func. The in keyword is used to separate the input parameters from the return part.

闭包是一种没有关键字func的匿名函数。 in关键字用于将输入参数与返回部分分开。

An example of closures is:

闭包的示例是:

var closureToAdd: (Int, Int) -> Int = { (a, b) in
        return a + b
    }
print(closureToAdd(10,5)) //prints 15

The input parameters are Int followed by -> and the return type again an Int.

输入参数为Int,后跟->,返回类型再次为Int。

We can call a closure similar to the way we call functions.

我们可以像调用函数一样调用闭包。

The output of the above application in action is below.

上面的应用程序的输出如下。

This brings an end to this tutorial. You can download the iOS UISearchController example project from the link given below.

本教程到此结束。 您可以从下面给出的链接下载iOS UISearchController示例项目。

Reference: Official Documentation

参考: 官方文档

翻译自: https://www.journaldev.com/14126/ios-uisearchcontroller-uitableview

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值