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

时间:2014-05-01 15:01:47

标签: ios uitableview uisearchbar uisearchdisplaycontroller

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

<UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate,UISearchDisplayDelegate>

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

    NSArray*     OldList;
    NSArray*     filteredList;

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

- (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进行任何更改,没有链接,也没有其他任何内容。如果我编译我得到我的表,但显然如果我尝试搜索某些东西,没有任何作用。此外,如果我向下滚动到表的末尾,应用程序崩溃。真正的问题是我无法看到搜索栏正常工作。有人可以帮帮我吗?

1 个答案:

答案 0 :(得分:19)

嗯,你正确地走上正轨......这与你的控制器类与你的控制器xib的连接完全一致。

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

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

我已阅读Apple Documentation。我建议你这样做,以帮助你理解这一点。

第一步:

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

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

@property (nonatomic, strong) UISearchDisplayController *searchController;

以下代码介绍了如何初始化和设置UISearchBarUISearchDisplayController的相应属性。如果您以编程方式在代码中创建UITableViewController,则还需要为其设置数据源和委托(未显示以使代码易于阅读)。

您有两个选择 - 您选择哪一个取决于您的代码和您希望实现的目标 - 您可以在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;
}

选项二 - 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方法中放置以下代码行...

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

第二步:

注意:

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

  • 可以使用oldList调用表示过滤数据集(filteredList)的表视图。

当您准备好self.searchController.searchResultsTableView数据源方法时,我怀疑您有其他数据源(可能是委托)方法需要在它们能够之前通知哪个表视图是当前表视图功能正常,为您提供完全可操作的搜索结果表视图和搜索功能。

例如:

tableView:cellForRowAtIndexPath:

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

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

第三步:

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

我更喜欢创建一个单独的nib文件(称为&#34; TableViewCellSearch.xib&#34;),其中包含一个表视图单元格,其中包含重用标识符&#34; SearchCell&#34;,然后将代码放入在以下- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (tableView == self.searchController.searchResultsTableView) return [self.filteredList count]; return [self.oldList count]; } 委托方法中注册此nib并重用标识符。

值得注意的是,此代码在UISearchDisplayController / init / awakeFromNib上面的代码块示例之后同样有效。

viewDidLoad

尝试这些建议。

希望这有帮助。