在我的 TableView 中实现 SearchBar 并使用 NSFetchedResultsController 和适当的谓词来使搜索工作

Posted

技术标签:

【中文标题】在我的 TableView 中实现 SearchBar 并使用 NSFetchedResultsController 和适当的谓词来使搜索工作【英文标题】:Implementing a SearchBar inside my TableView and using NSFetchedResultsController and the appropriate predicate to get searches working 【发布时间】:2013-10-25 07:02:31 【问题描述】:

我有一个简单的 TableViewController,它有一个添加按钮,可以转到 ModalViewController;用户将文本添加到文本字段中,按保存并关闭,该条目将添加到核心数据中的实体和属性并显示在 TableViewController 中。它运作良好。

我首先从另一个按钮开始,该按钮在表格视图中拉出 UISearchBar,我可以搜索结果并将其拉回;那行得通。然后,我在 TableViewController 的底部添加了一个新选项卡,并设法在其中获取了搜索栏和表格。

现在,我希望 SearchBar 位于 Single Table View 的顶部,并且我希望用户能够键入并让它动态搜索 TableView。

我的 fetchRequest 目前对于 TableView 看起来像这样(没有搜索栏):

 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"occasion.dateOfEvent" ascending:NO selector:@selector(localizedCaseInsensitiveCompare:)];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
    [fetchRequest setFetchBatchSize:20];
    //NSPredicate *pred = [NSPredicate predicateWithFormat:@"ANY whoBy.name CONTAINS[c] %@", self.searchBar.text];
    //[fetchRequest setPredicate:pred];
    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"occasion.dateOfEvent" cacheName:nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;
    return _fetchedResultsController;

我正在搜索 Transaction 等。现在,此代码与我的其他具有搜索栏的视图控制器之间的唯一区别是 NSPredicate 未注释这一事实。搜索效果很好。如果我在这段代码中取消注释,当我运行它时,我会收到以下错误:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid predicate: nil RHS'
*** First throw call stack:

我了解发生了什么,因为我希望 TableViewController 显示时没有谓词,但是当我搜索时,我使那个谓词生效。任何有关如何开始这项工作的帮助将不胜感激!

我的搜索栏委托方法如下所示:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error])
    
        NSLog(@"Error in search %@, %@", error, [error userInfo]);
     else
    
        [self.tView reloadData];
        [self.searchBar resignFirstResponder];
        [noResultsLabel setHidden:_fetchedResultsController.fetchedObjects.count > 0];
    

【问题讨论】:

【参考方案1】:

只有在给出搜索字符串时才应该设置谓词:

if ([self.searchBar.text length] > 0) 
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"ANY whoBy.name CONTAINS[c] %@", self.searchBar.text];
    [fetchRequest setPredicate:pred];

如果搜索字符串为空,则不设置谓词,因此返回所有结果。

【讨论】:

谢谢马丁 - 一如既往,你是一个很大的帮助!这摆脱了错误,断点显示它正在进入 searchbar 方法,但它没有刷新页面,或重新加载数据以显示显示结果。我已经更新了我的原始问题,以包含搜索栏是单独 UI 时的原始搜索栏方法,不同之处在于它正在重新加载数据,但我认为使用 NSFetched,我们不需要这样做。我也不需要在我的 TableViewController 中有一个 tableView 属性。当按下保存按钮时,有没有办法“重新加载”数据? @amitsbajaj:难道searchBarSearchButtonClicked 中的[self fetchedResultsController] 会返回一个 获取的结果控制器吗?如果谓词更改,您必须重新创建 FRC。 (这几乎是正确的。您也可以修改 fetch 请求。) 谢谢@Martin - 我认为 fetchedResultsController 是一样的。但是,在 fetchRquest 中,我有 if (_fetchedResultsController != nil) return _fetchedResultsController; 我不完全确定该怎么做才能使它正常工作,抱歉! @amitsbajaj:您可能应该在searchBarSearchButtonClicked 中设置_fetchedResultsController = nil,以便下一次调用[self fetchedResultsController] 创建一个 FRC。 谢谢 Martin - 试过了 - 不幸的是没有改变.. 当我用字母或单词按 Search 时,它会删除键盘但保留完整的项目列表,而不仅仅是搜索的术语.. 抱歉,我知道这不是太难,但我感谢您抽出时间提供帮助!

以上是关于在我的 TableView 中实现 SearchBar 并使用 NSFetchedResultsController 和适当的谓词来使搜索工作的主要内容,如果未能解决你的问题,请参考以下文章

在 TableView 中实现 CoreData 时遇到问题

如何在 tableView 单元格中实现收藏按钮?

迅速;带有tableView的scrollView可行吗?

在A section tableview中实现加载更多

静态 TableView 透明表头

Swift:使用界面生成器创建 tableView