UISearchController 搜索视图控制器

前言

  • UISearchDisplayController

    • Objective-C

      1
      2
      NS_CLASS_DEPRECATED_IOS(3_0, 8_0, "UISearchDisplayController has been replaced with UISearchController")
      @interface UISearchDisplayController : NSObject
    • Swift

      1
      2
      3
      @available(iOS, introduced=3.0, deprecated=8.0, message="UISearchDisplayController has been replaced with 
      UISearchController")
      public class UISearchDisplayController : NSObject
  • UISearchController

    • Objective-C

      1
      2
      NS_CLASS_AVAILABLE_IOS(8_0) @interface UISearchController : UIViewController 
      <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>
    • Swift

      1
      2
      @available(iOS 8.0, *) public class UISearchController : UIViewController, 
      UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning
  • 在 iOS 8.0 以上版本中, 我们可以使用 UISearchController 来非常方便地在 UITableView 中添加搜索框. 而在之前版本中, 我们还是必须使用 UISearchDisplayController + UISearchBar 的组合方式.

  • 我们创建的 tableView 和搜索控制器创建的 tableView 都会走代理方法,需要在代理方法中判断响应代理方法的 tableView 是哪一个,如果响应代理方法的 tableView 不是我创建的,说明一定是搜索控制器创建的。在 iOS 8.0 以下版本中需使用 tableView == myTableView 判断,在 iOS 8.0 以上版本中需使用 mySearchController.active 判断。

1、搜索框的创建

1.1 在 iOS 8.0 以下版本中

  • Objective-C

    • 遵守协议 UISearchDisplayDelegate

    • 搜索结果数组初始化

      1
      2
      3
      4
      5
      // 声明搜索结果存放数组
      @property(nonatomic, retain)NSMutableArray *mySearchResultArray;

      // 初始化搜索结果存放数组
      mySearchResultArray = [[NSMutableArray alloc] init];
    • searchDisplayController 初始化

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      // 声明搜索控制器,自带一个表格视图,用来展示搜索结果,必须设置为全局变量
      @property(nonatomic, retain)UISearchDisplayController *mySearchDisplayController;

      // 实例化搜索条
      UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];

      // 实例化搜索控制器对象
      mySearchDisplayController = [[UISearchDisplayController alloc]
      initWithSearchBar:searchBar
      contentsController:self];
      // 设置搜索控制器的代理
      mySearchDisplayController.delegate = self;

      // 为搜索控制器自带 tableView 指定代理
      mySearchDisplayController.searchResultsDelegate = self;
      mySearchDisplayController.searchResultsDataSource = self;

      // 将搜索条设置为 tableView 的表头
      myTableView.tableHeaderView = searchBar;
    • UISearchDisplayDelegate 协议方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      // 更新搜索结果
      /*
      只要搜索框的文字发生了改变,这个方法就会触发。searchString 为搜索框内输入的内容。
      */
      - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {

      // 清空上一次搜索的内容
      [mySearchResultArray removeAllObjects];

      // 将搜索的结果存放到数组中
      for (NSArray *subArray in myDataArray) {
      for (NSString *str in subArray) {

      NSRange range = [str rangeOfString:searchString];

      if (range.length) {
      [mySearchResultArray addObject:str];
      }
      }
      }
      return YES;
      }
    • UITableView 协议方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      // 设置分段头标题
      - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

      if (tableView == myTableView) {
      return [NSString stringWithFormat:@"%c", (char)('A' + section)];
      }
      return @"搜索结果";
      }

      // 设置分段数
      - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

      if (tableView == myTableView) {
      return myDataArray.count;
      }
      return 1;
      }

      // 设置行数
      - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

      if (tableView == myTableView) {
      return [[myDataArray objectAtIndex:section] count];
      }
      return mySearchResultArray.count;
      }

      // 设置每段显示的内容
      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testIdentifier"];

      if (!cell) {
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"testIdentifier"];
      }

      if (tableView == myTableView) {
      cell.textLabel.text = [[myDataArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
      }
      else {
      cell.textLabel.text = [mySearchResultArray objectAtIndex:indexPath.row];
      }

      return cell;
      }
  • Swift

    • 遵守协议 UISearchDisplayDelegate

    • 搜索结果数组初始化

      1
      2
      // 初始化搜索结果存放数组
      var mySearchResultArray: [String] = Array()
    • searchDisplayController 初始化

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      // 声明搜索控制器,自带一个表格视图,用来展示搜索结果,必须设置为全局变量
      var mySearchDisplayController:UISearchDisplayController!

      // 实例化搜索条
      let searchBar: UISearchBar = UISearchBar(frame: CGRectMake(0, 0, self.view.frame.size.width, 44))

      // 实例化搜索控制器对象
      mySearchDisplayController = UISearchDisplayController(searchBar: searchBar,
      contentsController: self)

      // 设置搜索控制器的代理
      mySearchDisplayController.delegate = self

      // 为搜索控制器自带 tableView 指定代理
      mySearchDisplayController.searchResultsDelegate = self
      mySearchDisplayController.searchResultsDataSource = self

      // 将搜索条设置为 tableView 的表头
      myTableView.tableHeaderView = searchBar
    • UISearchDisplayDelegate 协议方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      // 更新搜索结果
      /*
      只要搜索框的文字发生了改变,这个方法就会触发。searchString 为搜索框内输入的内容
      */
      func searchDisplayController(controller: UISearchDisplayController, shouldReloadTableForSearchString searchString: String?) -> Bool {

      // 清空上一次搜索的内容
      mySearchResultArray.removeAll()

      // 将搜索的结果存放到数组中
      for subArray in myDataArray {
      for str in subArray {

      let range:NSRange = (str as NSString).rangeOfString(searchString!)

      if range.length != 0 {
      mySearchResultArray.append(str)
      }
      }
      }

      return true
      }
    • UITableView 协议方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      // 设置分段头标题
      func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

      if tableView == myTableView {
      return "\(Character(UnicodeScalar(65 + section)))"
      }
      return "搜索结果"
      }

      // 设置分段数
      func numberOfSectionsInTableView(tableView: UITableView) -> Int {

      if tableView == myTableView {
      return myDataArray.count
      }
      return 1
      }

      // 设置行数
      func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

      if tableView == myTableView {

      return myDataArray[section].count
      }
      return mySearchResultArray.count
      }

      // 设置每段显示的内容
      func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

      var cell = tableView.dequeueReusableCellWithIdentifier("testIdentifier")

      if cell == nil {
      cell = UITableViewCell(style: .Default, reuseIdentifier: "testIdentifier")
      }

      if tableView == myTableView {
      cell!.textLabel?.text = myDataArray[indexPath.section][indexPath.row]
      }
      else {
      cell!.textLabel?.text = mySearchResultArray[indexPath.row]
      }

      return cell!
      }

1.2 在 iOS 8.0 及以上版本中

  • Objective-C

    • 遵守协议 UISearchResultsUpdating

    • 搜索结果数组初始化

      1
      2
      3
      4
      5
      // 声明搜索结果存放数组
      @property(nonatomic, retain)NSMutableArray *mySearchResultArray;

      // 初始化搜索结果存放数组
      mySearchResultArray = [[NSMutableArray alloc] init];
    • searchController 初始化

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      // 声明搜索控制器,自带一个表格视图控制器,用来展示搜索结果,必须设置为全局变量
      @property(nonatomic, retain)UISearchController *mySearchController;

      // 实例化搜索控制器
      mySearchController = [[UISearchController alloc] initWithSearchResultsController:nil];

      // 设置搜索代理
      mySearchController.searchResultsUpdater = self;

      // 设置搜索条大小
      [mySearchController.searchBar sizeToFit];

      // 设置搜索期间背景视图是否取消操作,default is YES
      mySearchController.dimsBackgroundDuringPresentation = NO;

      // 设置搜索期间是否隐藏导航条,default is YES
      mySearchController.hidesNavigationBarDuringPresentation = NO;

      // 将 searchBar 添加到表格的开头
      myTableView.tableHeaderView = mySearchController.searchBar;
    • UISearchResultsUpdating 协议方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      // 更新搜索结果
      /*
      只要搜索框的文字发生了改变,这个方法就会触发。searchController.searchBar.text 为搜索框内输入的内容
      */
      - (void)updateSearchResultsForSearchController:(UISearchController *)searchController {

      // 清除上一次的搜索结果
      [mySearchResultArray removeAllObjects];

      // 将搜索的结果存放到数组中
      for (NSArray *subArray in myDataArray) {
      for (NSString *str in subArray) {

      NSRange range = [str rangeOfString:searchController.searchBar.text];

      if (range.length) {
      [mySearchResultArray addObject:str];
      }
      }
      }

      // 重新加载表格视图,不加载的话将不会显示搜索结果
      [myTableView reloadData];
      }
    • UITableView 协议方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      // 设置分段头标题
      - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

      if (mySearchController.active) {

      return @"搜索结果";
      }
      return [NSString stringWithFormat:@"%c", (char)('A' + section)];
      }

      // 设置分段数
      - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

      if (mySearchController.active) {

      return 1;
      }
      return myDataArray.count;
      }

      // 设置行数
      - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

      if (mySearchController.active) {

      return mySearchResultArray.count;
      }
      return [[myDataArray objectAtIndex:section] count];
      }

      // 设置每段显示的内容
      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testIdentifier"];

      if (!cell) {
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"testIdentifier"];
      }

      if (mySearchController.active) {
      cell.textLabel.text = [mySearchResultArray objectAtIndex:indexPath.row];
      }
      else {
      cell.textLabel.text = [[myDataArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
      }

      return cell;
      }
  • Swift

    • 遵守协议 UISearchResultsUpdating

    • 搜索结果数组初始化

      1
      2
      // 初始化搜索结果存放数组
      var searchResultArray:[String] = Array()
    • searchController 初始化

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      // 声明搜索控制器,自带一个表格视图控制器,用来展示搜索结果,必须设置为全局变量
      var mySearchController:UISearchController!

      // 实例化搜索控制器
      mySearchController = UISearchController(searchResultsController: nil)

      // 设置搜索代理
      mySearchController.searchResultsUpdater = self

      // 设置搜索条大小
      mySearchController.searchBar.sizeToFit()

      // 设置搜索期间背景视图是否取消操作,default is YES
      mySearchController.dimsBackgroundDuringPresentation = false

      // 设置搜索期间是否隐藏导航条,default is YES
      mySearchController.hidesNavigationBarDuringPresentation = false

      // 将 searchBar 添加到表格的开头
      myTableView.tableHeaderView = mySearchController.searchBar
    • UISearchResultsUpdating 协议方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      // 更新搜索结果
      /*
      只要搜索框的文字发生了改变,这个方法就会触发。searchController.searchBar.text 为搜索框内输入的内容
      */
      func updateSearchResultsForSearchController(searchController: UISearchController) {

      // 清除上一次的搜索结果
      searchResultArray.removeAll()

      // 将搜索的结果存放到数组中
      for subArray in myDataArray {
      for str in subArray {

      let range:NSRange = (str as NSString).rangeOfString(searchController.searchBar.text!)

      if range.length != 0 {
      searchResultArray.append(str)
      }
      }
      }

      // 重新加载表格视图,不加载的话将不会显示搜索结果
      myTableView.reloadData()
      }
    • UITableView 协议方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      // 设置分段头标题
      func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

      if mySearchController.active {
      return "搜索结果"
      }
      return "\(Character(UnicodeScalar(65 + section)))"
      }

      // 设置分段数
      func numberOfSectionsInTableView(tableView: UITableView) -> Int {

      if mySearchController.active {

      return 1
      }
      return myDataArray.count
      }

      // 设置行数
      func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

      if mySearchController.active {

      return searchResultArray.count
      }
      return myDataArray[section].count
      }

      // 设置每段显示的内容
      func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

      var cell = tableView.dequeueReusableCellWithIdentifier("testIdentifier")

      if cell == nil {
      cell = UITableViewCell(style: .Default, reuseIdentifier: "testIdentifier")
      }

      if mySearchController.active {
      cell!.textLabel?.text = searchResultArray[indexPath.row]
      }
      else {
      cell!.textLabel?.text = myDataArray[indexPath.section][indexPath.row]
      }

      return cell!
      }
文章目录
  1. 1. 前言
  2. 2. 1、搜索框的创建
    1. 2.1. 1.1 在 iOS 8.0 以下版本中
    2. 2.2. 1.2 在 iOS 8.0 及以上版本中
隐藏目录