【问题标题】:How to use NSFetchedResultsController and UISearchDisplayController如何使用 NSFetchedResultsController 和 UISearchDisplayController
【发布时间】:2011-01-12 17:14:32
【问题描述】:

我一直在使用 Core Data 创建一个 iPhone 应用程序。

首先,同时使用 NSFetchedResultsController 和 UISearchDisplayController 来获取结果有意义吗?你会推荐其他东西吗?

我已经尝试了很长时间将 NSFetchedResultController 和 UISearchDisplayController 结合起来。我一直在考虑将(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption 方法中的NSPredicate 设置为UIViewController 的NSFetchedResultController。但这并没有那么好。

那么,您知道如何针对我的问题实施解决方案吗?感谢您发布答案或指向优秀教程的链接。

编辑

这是我的代码。 UISearchDisplayDelegate 方法调用方法(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope 应该在NSFetchedResultController 中设置谓词。我还添加了 NSFetchedResultController 的代码。

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

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
     [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}


- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSString *query = self.searchDisplayController.searchBar.text;
    if (query && query.length) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Name contains[cd] %@", query];
        [fetchedResultsController.fetchRequest setPredicate:predicate];
    }

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

}


- (NSFetchedResultsController *)fetchedResultsController {

    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    /*
     Set up the fetched results controller.
    */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    return fetchedResultsController;
} 

【问题讨论】:

    标签: iphone core-data nsfetchedresultscontroller uisearchdisplaycontroller


    【解决方案1】:

    看看你的代码,它就在那里。我在使用这种方法更改搜索时遇到了问题。解决方法:清除缓存!

    假设您按如下方式启动了获取的结果控制器。注意 cacheName 属性。

        NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:[self fetchRequest] managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"UserSearch"];
    

    当您更改谓词时,只需添加:

     [NSFetchedResultsController deleteCacheWithName:@"UserSearch"];
    

    就像魔术一样,它会很好地工作。

    您还需要监控搜索显示控制器何时结束其搜索,并擦除您的谓词。

    虽然这个帖子看起来已经死了,但我在 google 上找到了它,所以也许有人会使用它。 :)

    【讨论】:

    • 此解决方案有效,但相当昂贵,迫使获取的结果控制器多次访问持久存储。另外,如果你不打算使用缓存,为什么要指定一个呢?只是通过零。然而,@psuedonick 暗示的更好的解决方案是:让 fetchedResultsController 做它最擅长的事情,即管理获取的结果,并在 fetchedObjects 上使用 filtersArrayUsingPredicate: 来填充filteredListContent。
    • 澄清一下,如果您使用我描述的解决方案,您应该指定一个缓存:获取的结果控制器将需要它来存储 fetchedObject,以便可以有效地搜索它们通过filteredArrayUsingPredicate:
    • 谢谢伊莉丝,我认为你的方式是要走的路。稍后我将在另一篇文章中总结在表格视图控制器中实现搜索显示控制器的步骤。我花了很多时间来寻找关于这个问题的最佳实践。
    • 我的文章总结了在表格视图中实现搜索的步骤在这里:stackoverflow.com/questions/12555208/…
    【解决方案2】:

    根据文档,您要么希望使用谓词将结果过滤到数组中,要么重新初始化 fetchedResultsController。

    重要提示:您不得修改 获取请求后 初始化控制器。为了 例如,您不得更改 谓词或排序顺序。

    -- NSFetchedResultsController

    (我会评论空闲的答案,但我没有业力。)

    【讨论】:

      【解决方案3】:

      听起来您只是对获取和显示对象感兴趣。在这种情况下,您不使用搜索显示控制器。搜索显示控制器与搜索栏一起使用,以帮助允许用户输入文本搜索您的内容。

      通常您使用获取的结果控制器来帮助您实现表视图数据源和委托方法。此外,您为获取的结果控制器创建和使用获取请求。这都是样板文件(当您创建一个新项目并选择“使用核心数据进行存储”选项时,请参阅 Apple 提供的模板代码)。

      您可以在获取请求中创建和指定谓词。这将允许您过滤表格显示的对象。例如:

      // only fetch objects with myAttribute set to someValue
      NSPredicate *pred = [NSPredicate predicateWithFormat:@"myAttribute == %@",someValue];
      [fetchRequest setPredicate:pred];
      

      【讨论】:

      • 好吧,我还没有清楚地提到我实际上正在实施一个小搜索。我已经尝试在 NSFetchedResultsController 中设置谓词来过滤结果,就像您发布的代码一样,但是没有任何反应,没有找到任何对象。知道为什么谓词不起作用吗?这只是搜索字符串和对象名称之间的简单比较。感谢您的帮助
      • 您应该添加有关谓词的详细信息或询问有关它的新问题。此外,最好在提问时展示您使用的代码。
      猜你喜欢
      • 2011-05-27
      • 1970-01-01
      • 2013-09-14
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多