在表视图中搜索栏和搜索显示控制器

The*_*One 1 uitableview uisearchbar uisearchdisplaycontroller ios

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

<UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate,UISearchDisplayDelegate>
Run Code Online (Sandbox Code Playgroud)

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

    NSArray*     OldList;
    NSArray*     filteredList;
Run Code Online (Sandbox Code Playgroud)

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

- (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;
}
Run Code Online (Sandbox Code Playgroud)

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

and*_*der 19

那么你是在正确的轨道上...它与控制器类与控制器xib的连接完全相同.

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

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

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

第一步:

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

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

@property (nonatomic, strong) UISearchDisplayController *searchController;
Run Code Online (Sandbox Code Playgroud)

以下代码描述了如何初始化和设置a UISearchBar和a 的相应属性UISearchDisplayController.如果以编程方式创建UITableViewControllerin代码,则还需要为其设置数据源和委托(未显示以使代码易于阅读).

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

选项一 - 初始化

(注1:Paul Hegarty非凡的iTunesU讲座教会我按照以下方式启动/唤醒课程 - 这样你就可以了解这两种情况 - 你可以调用init或者它可以唤醒.FromNib.)

- (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;
}
Run Code Online (Sandbox Code Playgroud)

要么

选项二 - 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 >...
}
Run Code Online (Sandbox Code Playgroud)

注2:无论您选择哪种选项,都需要在方法中放置以下代码行viewDidLoad...

    [self.tableView setTableHeaderView:self.searchController.searchBar]; // (or just searchBar)
Run Code Online (Sandbox Code Playgroud)

第二步:

笔记:

  • OldList可以使用表示完整数据集()的表视图self.tableView(PS约定是以小写字母启动每个变量 - 因此将属性名称从更改OldListoldList).

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

在准备好tableView:cellForRowAtIndexPath:数据源方法的同时,我怀疑你有其他的数据源(也许是委托)方法需要被告知哪个表视图是当前的表视图,然后它们才能正常运行并为你提供一个完整的操作搜索结果表视图和搜索功能.

例如:

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

和:

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

请注意,可能有其他数据源(可能是委托)方法需要通知哪个表视图是当前表视图...我将留给您确定要修改哪些方法,以及调整表视图所需的相应代码.

第三步:

您将需要为搜索结果表视图注册一个nib并重用标识符.

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

值得注意的是,在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];
}
Run Code Online (Sandbox Code Playgroud)

试试这些建议.

希望这可以帮助.