【问题标题】:Adding UISearchBar programmatically to UITableView以编程方式将 UISearchBar 添加到 UITableView
【发布时间】:2011-10-20 08:14:44
【问题描述】:

我正在尝试添加一个UISearchBar(及其相应的搜索逻辑),但有一个问题:我使用的是UITableViewController 子类自动生成的UITableView 而不是单独的nib 文件,并处理所有内容根据表格视图以编程方式。

在 Interface Builder 中,可以选择将 Search BarSearch Display Controller 添加到 nib。有没有办法以编程方式完成同样的任务,还是放弃默认的UITableView 并转移到自定义的UITableView nib 文件以便我可以轻松添加UISearchbar 对我有利?

另外,我已经尝试通过我的viewDidLoad 实现中的以下代码在我的UITableView 标题(这是我想要它去的地方)中添加一个搜索栏,但它显示在表格部分标题后面因此是不可见的,除非向下滚动表格以显示其他情况下的空白。这是怎么回事?

UISearchBar *testbar = [[UISearchBar alloc] init];

[[self tableView] setTableHeaderView:testbar];

【问题讨论】:

    标签: iphone uitableview interface uisearchbar


    【解决方案1】:

    要将 UISearchBar 添加到 UITableView,需要执行以下操作:

    • 声明并初始化 UISearchBar
    • 声明并初始化 UISearchDisplayController
    • 将 searchBar 添加到 tableView
    • 实现 UISearchDisplayController 委托
    • 在头文件中,我声明了我的 searchBar、searchDisplayController 和包含要显示的数据的数组。

    ViewController.h:

    #import 
    
    @interface ViewController : UITableViewController
    {
        NSArray *originalData;
        NSMutableArray *searchData;
    
        UISearchBar *searchBar;
        UISearchDisplayController *searchDisplayController;
    }
    
    @end
    

    我还在该类中添加了 2 个委托:UISearchBarDelegate 和 UISearchDisplayDelegate,没有,searchBar 根本不起作用!

    初始化数据:

    //ViewController.m
    
    - (id)initWithStyle:(UITableViewStyle)style
    {
        self = [super initWithStyle:style];
        if (self) {
            NSArray *group1 = [[NSArray alloc] initWithObjects:@"Napoli", @"Juventus", @"Inter", @"Milan", @"Lazio", nil];
            NSArray *group2 = [[NSArray alloc] initWithObjects:@"Real Madrid", @"Barcelona", @"Villareal", @"Valencia", @"Deportivo", nil];
            NSArray *group3 = [[NSArray alloc] initWithObjects:@"Manchester City", @"Manchester United", @"Chelsea", @"Arsenal", @"Liverpool", nil];
    
            originalData = [[NSArray alloc] initWithObjects:group1, group2, group3, nil];
            searchData = [[NSMutableArray alloc] init];
        }
        return self;
    }
    

    现在我们需要初始化我们的两个对象,我注释了代码来解释我的工作:

    //ViewController.m
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    /*the search bar widht must be > 1, the height must be at least 44
    (the real size of the search bar)*/
    
        searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
    /*contents controller is the UITableViewController, this let you to reuse
    the same TableViewController Delegate method used for the main table.*/
    
        searchDisplayController.delegate = self;
        searchDisplayController.searchResultsDataSource = self;
    //set the delegate = self. Previously declared in ViewController.h
    
        self.tableView.tableHeaderView = searchBar; //this line add the searchBar
                                                    //on the top of tableView.
    }
    

    我决定跳过有关 tableView 单元初始化的部分,您可以在可下载的源代码中找到它。 :)

    当 tableView 准备好后,就可以实现 UISearchDisplayControllerDelegate 了!

    委托有很多方法来控制搜索的各个方面,但最重要的是

    - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
    

    每次在 searchBar 中插入新字符时都会调用此方法,您将获取 searchString,通过表格元素执行搜索并返回 YES。

    - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
    {
        [searchData removeAllObjects];
        /*before starting the search is necessary to remove all elements from the
          array that will contain found items */
    
        NSArray *group; 
    
    /* in this loop I search through every element (group) (see the code on top) in
    the "originalData" array, if the string match, the element will be added in a
    new array called newGroup. Then, if newGroup has 1 or more elements, it will be
    added in the "searchData" array. shortly, I recreated the structure of the
    original array "originalData". */
    
        for(group in originalData) //take the n group (eg. group1, group2, group3)
                                   //in the original data
        {
            NSMutableArray *newGroup = [[NSMutableArray alloc] init];
            NSString *element;
    
            for(element in group) //take the n element in the group
            {                    //(eg. @"Napoli, @"Milan" etc.)
                NSRange range = [element rangeOfString:searchString
                                         options:NSCaseInsensitiveSearch];
    
                if (range.length > 0) { //if the substring match
                    [newGroup addObject:element]; //add the element to group
                }
            }
    
            if ([newGroup count] > 0) {
                [searchData addObject:newGroup];
            }
    
            [newGroup release];
        }
    
        return YES;
    }
    

    就是这样!此方法将在所有元素中执行全文搜索。当搜索结束时,tableView 会自行重新加载。查看源代码以查看其他详细信息。

    Download source file (Link UPDATED! (04.01.2016) )

    【讨论】:

    • 在 viewDidLoad 我还必须包含这一行:searchDisplayController.searchResultsDataSource = self;否则 tableView 不会被 shouldReloadTableForSearchString 重新加载
    • 下载链接损坏。
    • 能否提供下载代码的活动链接?
    • 对不起,我丢失了示例代码,网站不再在线:(
    • 更新:我在旧硬盘中找到了示例代码! :) 这里是:aurealab.net/minux/UISearchBarSample.zip
    【解决方案2】:

    为 UISearchBar 设置框架:

    // Change the position according to your requirements
    self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 70, 320, 44)];
    

    如果您的视图是UITableViewController 的子类,请将其更改为UIViewController

    • 在您的 nib 文件中,创建一个视图并将您的 tableView 拖到该视图下 查看并将该视图的参考类更改为您的 UIViewController

    • 创建IBOutletUITableView * myTableView 并将其连接到 你的笔尖文件。您只需将您的 VC 文件(例如 self)更改为 [self.myTableView reloadData];

    现在您可以调整笔尖本身的tableView 和搜索栏。

    UISearchDisplay 控制器有自己的UITableView,它显示由另一个视图控制器管理的数据的搜索结果。这里searchDisplaycontroller 结合了搜索栏和tableview 以在tableview 中显示结果数据,因此不需要单独的tableview。

    【讨论】:

    • 嗯所以这解决了问题?这就是为什么我对你说根据你的要求改变位置。我也更新了我的答案:)
    • 对不起,我写的评论很快。我想说的是 (0, 0, 320, 44) 是唯一可能的框架,因为表头视图始终位于左上角并占据全宽,而 UISearchBar 始终为 44px 高度。你可以设置任何你想要的,它会有这个框架
    • 你添加了一个不必要的过程,我已经复制了他的问题并且这个工作: UISearchBar *testbar = [[UISearchBar alloc] initWithFrame:CGRectMake(0,170,320,44)]; [[self tableView] setTableHeaderView:testbar];
    • 在我的第一个答案中,我只是告诉您更改框架然后您说“表头视图始终位于左上角并占据全宽,并且 UISearchBar 始终为 44px 高度。”所以我给了你第二个选择。 我没有在我的回答中说你应该删除 [[self tableView] setTableHeaderView:testbar];
    • 嗨,感谢您的帮助,它现在肯定出现在正确的位置(尽管如果可以的话,我总是厌倦使用 CGRectMakes 而不是委托方法。无论如何,我环顾四周,它出现了UITableView 有一个内置的 UISearchDisplay 控制器,所以我应该能够利用它而忘记 Interface Builder,对吧?
    【解决方案3】:

    实现- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section。这样就解决了section Label覆盖headerView的问题

    【讨论】:

      【解决方案4】:

      迅速:

          let searchController = UISearchController(searchResultsController: nil)
      
          let topConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 40)
          let leftConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 0)
          let rightConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Right, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Right, multiplier: 1, constant: 0)
          let heightConstraint = NSLayoutConstraint(item: searchController.searchBar, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 44)
          searchController.searchBar.translatesAutoresizingMaskIntoConstraints = false
      
          searchController.searchBar.addConstraint(heightConstraint)
      
          searchController.searchBar.placeholder = "Search Here"
          searchController.searchResultsUpdater = self
          searchController.searchBar.delegate = self
      
          self.view.addSubview(searchController.searchBar)
      
          self.view.addConstraints([topConstraint, leftConstraint, rightConstraint])
      

      添加委托:

          class ViewController: UIViewController, UISearchBarDelegate
      

      现在添加委托方法来重新加载表格视图:

          func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
              //add your custome code here after search a string
              tableView.reloadData()
          }
      
          func searchBarTextDidEndEditing(searchBar: UISearchBar) {
              //add your custome code here after finishing search 
              tableView.reloadData()
      
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-08
        • 2014-07-11
        • 1970-01-01
        相关资源
        最近更新 更多