iOS - UISearchController

本文介绍在iOS不同版本中实现搜索框的方法,包括使用UISearchDisplayController和UISearchController,并提供了Objective-C与Swift两种语言的代码示例。

前言

    NS_CLASS_DEPRECATED_IOS(3_0, 8_0, "UISearchDisplayController has been replaced with UISearchController")
    @interface UISearchDisplayController : NSObject
    
    @available(iOS, introduced=3.0, deprecated=8.0, message="UISearchDisplayController has been replaced with 
        UISearchController")
    public class UISearchDisplayController : NSObject


    NS_CLASS_AVAILABLE_IOS(8_0) @interface UISearchController : UIViewController 
        <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>
    @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

    • 搜索结果数组初始化

          // 声明搜索结果存放数组
          @property(nonatomic, retain)NSMutableArray *mySearchResultArray;
      
          // 初始化搜索结果存放数组
          mySearchResultArray = [[NSMutableArray alloc] init];
    • searchDisplayController 初始化

          // 声明搜索控制器,自带一个表格视图,用来展示搜索结果,必须设置为全局变量
          @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 协议方法

          // 更新搜索结果
          /*
              只要搜索框的文字发生了改变,这个方法就会触发。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 协议方法

          // 设置分段头标题
          - (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

    • 搜索结果数组初始化

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

          // 声明搜索控制器,自带一个表格视图,用来展示搜索结果,必须设置为全局变量
          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 协议方法

          // 更新搜索结果
          /*
              只要搜索框的文字发生了改变,这个方法就会触发。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 协议方法

          // 设置分段头标题
          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

    • 搜索结果数组初始化

          // 声明搜索结果存放数组
          @property(nonatomic, retain)NSMutableArray *mySearchResultArray;
      
          // 初始化搜索结果存放数组
          mySearchResultArray = [[NSMutableArray alloc] init];
    • searchController 初始化

          // 声明搜索控制器,自带一个表格视图控制器,用来展示搜索结果,必须设置为全局变量
          @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 协议方法

          // 更新搜索结果
          /*
              只要搜索框的文字发生了改变,这个方法就会触发。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 协议方法

          // 设置分段头标题
          - (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

    • 搜索结果数组初始化

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

          // 声明搜索控制器,自带一个表格视图控制器,用来展示搜索结果,必须设置为全局变量
          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 协议方法

          // 更新搜索结果
          /*
              只要搜索框的文字发生了改变,这个方法就会触发。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 协议方法

          // 设置分段头标题
          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!
          }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值