【问题标题】:NSFetchedResultsController with search带搜索的 NSFetchedResultsController
【发布时间】:2010-11-27 23:07:07
【问题描述】:

过滤NSFetchedResultsController 数据的最佳做法是什么? 每次搜索栏的文本发生变化时我都需要重新初始化它吗?

我正在使用UISearchDisplayControllers 并且我正在实施:

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

谢谢。

【问题讨论】:

标签: objective-c core-data nsfetchedresultscontroller


【解决方案1】:

Guy 的答案代码与问题有何不同?据我猜测,filterContentForSearchText:scope 方法是由 shouldReload 方法调用的?

无论如何,这是我在 CoreDataBooks 示例中添加的一些类似代码以包含搜索。在 IB 中为 CoreDataBooks 示例添加一个搜索显示控制器。然后我将代码添加到 RootViewController.m 如下:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
 NSInteger searchOption = controller.searchBar.selectedScopeButtonIndex;
 return [self searchDisplayController:controller shouldReloadTableForSearchString:searchString searchScope:searchOption];
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
 NSString* searchString = controller.searchBar.text;
 return [self searchDisplayController:controller shouldReloadTableForSearchString:searchString searchScope:searchOption];
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString*)searchString searchScope:(NSInteger)searchOption {

 NSPredicate *predicate = nil;
 if ([searchString length])
  if (searchOption == 0) // full text, in my implementation.  Other scope button titles are "Author", "Title"
   predicate = [NSPredicate predicateWithFormat:@"title contains[cd] %@ OR author contains[cd] %@", searchString, searchString];
  else
   // docs say keys are case insensitive, but apparently not so.
   predicate = [NSPredicate predicateWithFormat:@"%K contains[cd] %@", [[controller.searchBar.scopeButtonTitles objectAtIndex:searchOption] lowercaseString], searchString];
 [fetchedResultsController.fetchRequest setPredicate:predicate];

    NSError *error = nil;
    if (![[self fetchedResultsController] performFetch:&error]) {
  NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
  abort();
    }           

 return YES;
}

PS。为了回答 Vivas,它使用 UISearchDisplayController 自动创建一个新的表视图来覆盖过滤列表。您可以按照文档中的说明检查正在使用哪个 tableView,但在最简单的设置中,它可以正常工作,因为 fetchedResultsController 要么在搜索的表格视图中显示过滤后的版本,要么在表格视图中显示所有数据。

【讨论】:

  • 仍然很奇怪的行为...对象确实被过滤了,但是当我向下滚动表格视图时它会给出异常,因为 fetchController 在特定索引处没有对象...可能有什么问题?请帮忙
  • 我发现了我的问题...当我得到过滤结果时,它们会显示在以相同方式配置的 tableView 中,并且当我滚动到实际行数小于 X 的行号 X 时...我该怎么办..
【解决方案2】:

显然这是一个更好的方法:

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    self.savedSearchTerm = searchText;

    freshData = NO;
    if (searchText !=nil)
    {
            NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name contains[cd] %@", searchText];
            [fetchedResultsController.fetchRequest setPredicate:predicate];
    }
    else
    {
            NSPredicate *predicate =[NSPredicate predicateWithFormat:@"All"];
            [fetchedResultsController.fetchRequest setPredicate:predicate];
    }

    NSError *error = nil;
    if (![[self fetchedResultsController] performFetch:&error]) {
            // Handle error
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            exit(-1);  // Fail
    }           

    [self.tableView reloadData];

    //    [searchBar resignFirstResponder];   
    //    [_shadeView setAlpha:0.0f];

 }

【讨论】:

  • appl 文档说不应更改获取请求 - 他们明确表示您不应更改谓词。
  • @RogerNolan 你确定吗?查看NSFetchedResultsController Class Reference : Modifying the Fetch Request。这三个步骤对我来说很好,我什至修改了获取请求的谓词。
  • 这是一个改变(我认为)。无论哪种方式,说明基本上都是如果您更改请求,则必须重新发出搜索。
  • 我已编辑示例以调用 abort() 而不是 exit(-1)。正如 0xced 所说,也许两者都不应该做,但在 iOS 上调用 exit() 并不是一个好主意;调试 developer.apple.com/library/ios/qa/qa1561>. 时首选 abort()
  • 仅当您在现有的 tableview 中搜索时才有效。除此之外,这是一个很好的解决方案,代码更改非常少。了不起的兄弟。竖起大拇指
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多