表格视图中的搜索栏和搜索显示控制器 [英] Search Bar and Search Display Controller in table view

查看:24
本文介绍了表格视图中的搜索栏和搜索显示控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾尝试实现一个搜索栏,但我没有任何运气处理这个问题.我真的很感激可以提供的任何帮助.我有一个大项目,其中有一个表视图,我想在它上面实现一个搜索栏并查看实时过滤.我不使用 Storyboard,但我使用的是 XIB.我添加了以下协议:

I have tried to implement a search bar but I have not had any luck dealing with this problem. I would really appreciate any help that can be provided. I've a big project in which I've a table view, and I want to implement a search bar over it and see the real time filtering. I do not use Storyboard but I'm using XIB. I've added the following protocols:

<UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate,UISearchDisplayDelegate>

我在 @interface 中声明了 2 个数组,第一个用于整个元素,第二个用于过滤的元素:

I've declared 2 arrays in @interface , the first for the whole elements and the second one for the filtered ones:

    NSArray*     OldList;
    NSArray*     filteredList;

然后我设置了行数和节数,然后:

Then I've setted the number of rows and the number of sections and then:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    myClassCell *cell = [tableView dequeueReusableCellWithIdentifier:MYCELLCLASS];
    if (cell == nil)
    {
        cell = [myClassCell newFromNib];
    }
    NSMutableDictionary* elem = nil;
    if (tableView == self.searchDisplayController.searchResultsTableView)
    {
        elem = [filteredList objectAtIndex:indexPath.row];
        if ([elem count]+1 > indexPath.row)
            [cell showValues:elem];
        else
            [cell showValues:nil];
    }
    else
    {
        elem = [OldList objectAtIndex:indexPath.row];
        if ([elem count]+1 > indexPath.row) 
            [cell showValues:elem];
        else
            [cell showValues:nil];
    }
    return cell;
}

-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"name contains[c] %@", searchText];
    filteredist = [OldList filteredArrayUsingPredicate:resultPredicate];
}

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
    objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
    return YES;
}

此时,我还没有对 xib 进行任何更改,没有链接,也没有其他内容.如果我编译我得到我的表,但显然如果我尝试搜索某些东西,没有任何效果.此外,如果我向下滚动到表格的末尾,应用程序就会崩溃.真正的问题是我看不到搜索栏的工作.有人可以帮我吗?

At this point, I haven't done any changes to the xib, no links and no other stuffs. If I compile I get my table, but obviously if I try to search something, nothing works. Moreover if I scroll down to the end of the table the app crashes. The real problem is that I can't see the search bar working. Could someone help me please?

推荐答案

好吧,您走在正确的轨道上……这完全与您的控制器类与控制器 xib 的连接有关.

Well you're on the right track... it is exactly to do with the connection of your controller class to your controller xib.

当您想将搜索栏和搜索显示控制器初始化为 UITableView 时,您实际上是在添加第二个表视图,当激活该视图时,必须由您的 UITableViewController 类中的代码管理与任何 UITableView 相同的方式.

When you want to initialise a Search Bar and Search Display Controller into a UITableView, you are effectively adding a second table view that, when activated, must be managed by code in your UITableViewController class in the same manner as any UITableView.

我已经使用这些 SO 问题/答案来检查我自己的答案 - 我建议您看一看:

I have used these SO questions/answers to check my own answer - I recommend you take a look:

我已阅读 Apple 文档.我建议您也这样做以帮助您理解这一点.

I have read the Apple Documentation. I recommend you do the same to help you understand this.

当您运行控制器类时,您需要为两个表视图设置数据源和委托方法.

You will need to set data source and delegate methods for both table views when you run your controller class.

在您执行任何操作之前,请包含此属性...

Before you do any of this, include this property...

@property (nonatomic, strong) UISearchDisplayController *searchController;

以下代码描述了如何为 UISearchBarUISearchDisplayController 初始化和设置适当的属性.如果您在代码中以编程方式创建 UITableViewController,您还需要为其设置数据源和委托(未显示以保持代码易于阅读).

The following code describes how to initialise and set the appropriate properties for a UISearchBar and a UISearchDisplayController. If you are programmatically creating a UITableViewController in code you will also need to set the data source and delegate for it (not shown to keep the code easy to read).

您在这里有两个选项 - 您选择哪一个取决于您的代码和您希望实现的目标 - 在您的 init/awakeFromNib 方法中设置这些,或者设置这些在您的表视图控制器 (TVC) 生命周期方法之一中.

You have two options here - which one you choose depends on your code and what you wish to achieve - either set these in your init/awakeFromNib methods, or set these in one of your table view controller (TVC) lifecycle methods.

选项一 - 初始化

(注 1:Paul Hegarty 非凡的 iTunesU 讲座教会我按如下方式初始化/唤醒一个类——这样你就涵盖了两种情况——你调用 init 或者它可以awakeFromNib.)

(Note1: Paul Hegarty's extraordinary iTunesU lectures taught me to init/awake a class as follows - in this way you are covered for both scenarios - you call init or it can awakeFromNib.)

- (void)setup {
    //  Provide initialisation code here!!!
    UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
    [searchBar sizeToFit];
    [searchBar setDelegate:self];

    [self setSearchController:[[UISearchDisplayController alloc] initWithSearchBar:searchBar
                                                                contentsController:self]];
    [self.searchController setSearchResultsDataSource:self];
    [self.searchController setSearchResultsDelegate:self];
    [self.searchController setDelegate:self];
}

- (void)awakeFromNib {
    [self setup];
}

- (id)initWithStyle:(UITableViewStyle)style {
    self = [super initWithStyle:style];
    if (self) {
        [self setup];
    }
    return self;
}

选项二 - TVC 生命周期

- (void)viewDidLoad {
    [super viewDidLoad];

    UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
    [searchBar sizeToFit];
    [searchBar setDelegate:self];

    [self setSearchController:[[UISearchDisplayController alloc] initWithSearchBar:searchBar
                                                                contentsController:self]];
    [self.searchController setSearchResultsDataSource:self];
    [self.searchController setSearchResultsDelegate:self];
    [self.searchController setDelegate:self];

    [self.tableView setTableHeaderView:self.searchController.searchBar]; // see Note2

    ...< other code as required >...
}

注意 2:无论您选择这些选项中的哪一个,您都需要将以下代码行放入您的 viewDidLoad 方法中...

Note2: Regardless of which of these options you choose, you will need to place the following line of code in your viewDidLoad method...

    [self.tableView setTableHeaderView:self.searchController.searchBar]; // (or just searchBar)

第二步:

注意事项:

Second Step:

Notes:

  • 可以使用 self.tableView 调用代表您完整数据集 (OldList) 的表格视图(PS 约定是每个变量以小写开头- 因此将您的属性名称从 OldList 更改为 oldList).

  • The table view that represents your complete data set (OldList) can be called using self.tableView (PS convention is to start each variable with lower case - so change your property name from OldList to oldList).

可以使用self.searchController.searchResultsTableView调用表示过滤数据集(filteredList)的表格视图.

The table view that represents the filtered data set (filteredList) can be called using self.searchController.searchResultsTableView.

虽然您已经准备好 tableView:cellForRowAtIndexPath: 数据源方法,但我怀疑您还有其他数据源(可能还有委托)方法需要被告知哪个表视图是当前表视图, 在它们能够正常运行之前为您提供一个完全可操作的搜索结果表视图和搜索功能.

While you have prepared your tableView:cellForRowAtIndexPath: data source method, I suspect you have other data source (and maybe delegate) methods that need to be informed of which table view is the current table view, before they are able to function properly and provide you with a fully operational search results table view and search function.

例如:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if (tableView == self.searchController.searchResultsTableView)
        return 1;
    return [[self.oldList sections] count];;
}

和:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (tableView == self.searchController.searchResultsTableView)
        return [self.filteredList count];
    return [self.oldList count];
}

注意,可能还有其他数据源(也可能是delegate)方法需要被告知哪个表视图是当前的表视图……我会留给你来决定要修改这些方法中的哪些,以及调整表格视图所需的相应代码.

Note that there may be other data source (and maybe delegate) methods that need to be informed of which table view is the current table view... I will leave it to you to determine which of these methods are to be modified, and the corresponding code necessary to adjust the table view.

您需要为搜索结果表视图注册一个笔尖并重复使用标识符.

You will be required to register a nib and reuse identifier for your search results table view.

我更喜欢创建一个单独的 nib 文件(称为TableViewCellSearch.xib"),其中包含一个表视图单元格,重用标识符为SearchCell",然后将注册此笔尖和重用标识符的代码放在下面UISearchDisplayController 委托方法.

I prefer to create a separate nib file (called "TableViewCellSearch.xib") that contains one table view cell, with the reuse identifier "SearchCell", and then place the code to register this nib and reuse identifier in the following UISearchDisplayController delegate method.

值得注意的是,此代码与上述 init/awakeFromNib/viewDidLoad 中的代码块示例一样有效.

It is worth noting that this code is just as effective after the code block examples above in init/awakeFromNib/viewDidLoad.

- (void)searchDisplayController:(UISearchDisplayController *)controller willShowSearchResultsTableView:(UITableView *)tableView {
    static NSString *cellIdentifierSearch = @"SearchCell";
    UINib *nib = [UINib nibWithNibName:@"TableViewCellSearch" bundle:nil];
    [self.searchController.searchResultsTableView registerNib:nib forCellReuseIdentifier:cellIdentifierSearch];
}

试试这些建议.

希望这会有所帮助.

这篇关于表格视图中的搜索栏和搜索显示控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆