将UISearchBar与表视图控制器一起使用并转换到另一个视图时显示问题

Nei*_*fey 6 cocoa-touch uisearchbar ios

从iOS 8开始,我遇到了一个关于表视图/ UISearchBar设置的奇怪问题,并且想知道其他人是否遇到过类似的问题,或者可以指出什么,如果有的话,我可能做错了.广泛的情况:

  • 我有一个UITableViewController,里面有一个UISearchBar,在应用程序的Storyboard中设置
  • 表视图还有一个自定义单元格,再次在Storyboard中设置
  • 选择表格行会触发到另一个视图的segue
  • 执行搜索,从搜索结果中点击一行以切换到另一个视图,然后再次导航,触发各种问题.

"问题"是如果我按如下方式实现cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyCell *cell = (MyCell *) [self.tableView dequeueReusableCellWithIdentifier:@"MyId" forIndexPath:indexPath];
...
Run Code Online (Sandbox Code Playgroud)

换句话说,通过指定dequeueReusableCellWithIdentifier的路径,这会导致iOS 8中的BAD_ACCESS或断言失败(但不会导致iOS 7).具体来说,在上述情况下,在调用dequeueReusableCellWithIdentifier时发生断言失败或BAD_ACCESS,即,当搜索处于活动状态时,您将结果表中的一个单元格转换为另一个视图,然后再次进行转换.

现在,我可以通过调用来阻止错误发生:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyCell *cell = (MyCell *) [self.tableView dequeueReusableCellWithIdentifier:@"MyId"];
...
Run Code Online (Sandbox Code Playgroud)

没有传入indexPath.这样就可以正常工作,但是在使用搜索结果回到表格视图时,会出现奇怪的显示问题,从而在搜索结果下面分层,似乎是"鬼"表的分隔符,几乎就像系统正在尝试将一个表直接呈现在另一个表之上(但为每个表调用cellForRowAtIndexPath ,仅针对搜索结果表按预期调用).

无论segue是附加到单元格还是表视图控制器,我都会遇到同样的问题(所以在后一种情况下,我实现了didSelectRowAtIndexPath来手动触发segue).

那么:(a)任何人都可以指出我可能做错的事情导致这些问题,或者(b)指向一个带有UISearchBar的表视图控制器的简单工作示例,其中表格单元格转换到另一个视图?我很惊讶我遇到了很多问题,因为实现一个带有详细视图的可搜索表必须是一个人们常常做的常见,无聊的事情,不是吗?

展示iusse的示例项目: http ://www.javamex.com/DL/TableTest.zip

Log*_*ger 5

我下载了你的代码,我观察到的是,如果我改变了

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
Run Code Online (Sandbox Code Playgroud)

方法如下,对我来说工作正常.

解决方法1:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return [searchResults count];

    } else {
        return [testData count];

    }

}
Run Code Online (Sandbox Code Playgroud)

请告诉我它是否适合您,我的建议是使用"NSPredicate"来过滤数组,如下所示.

- (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    NSLog(@"Search text did change");

    NSPredicate *resultPredicate = [NSPredicate
                                    predicateWithFormat:@"SELF contains[cd] %@",
                                    searchText];

    searchResults = [testData filteredArrayUsingPredicate:resultPredicate];
}
Run Code Online (Sandbox Code Playgroud)

Nlote:将 "searchResults"作为NSArray而不是NSMutableArray.

上面的解决方案对我有用.这是解决问题的另一种方法.

溶液2:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    if (tableView == self.searchDisplayController.searchResultsTableView) {
        return [searchResults count];

    } else {
        return [testData count];

    }

}

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSPredicate *resultPredicate = [NSPredicate
                                    predicateWithFormat:@"SELF contains[cd] %@",
                                    searchText];

    searchResults = [testData filteredArrayUsingPredicate:resultPredicate];
}

// I implemented The following delegate method.


-(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)


fol*_*ben 2

实际上,使用任何一种方法将单元格出列到 main 中都没有问题tableView,尽管现在 indexPath 变体似乎是 Apple 的首选选项。

但是searchResultsTableView,请避免指定 indexPath,因为它不一定对视图控制器的tableView. 那是:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyTableViewCell *cell;
    if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]) {
        cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyCell"];
    } else {
        cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyCell" forIndexPath:indexPath];
    }
    // configure the cell
}
Run Code Online (Sandbox Code Playgroud)

为了使其正常工作,您还需要修改其他UITableViewDataSource方法。代替:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return (searchResults) ? (searchResults.count) : (testData.count);
}
Run Code Online (Sandbox Code Playgroud)

做:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]) {
        return searchResults.count;
    }
    return testData.count;
}
Run Code Online (Sandbox Code Playgroud)