Ios 基于NSFetchedResultsController中的NSPredicate筛选UITableView

Ios 基于NSFetchedResultsController中的NSPredicate筛选UITableView,ios,objective-c,uitableview,core-data,nsfetchedresultscontroller,Ios,Objective C,Uitableview,Core Data,Nsfetchedresultscontroller,我正在尝试筛选UITableView中的对象,该视图通过nsfetchedresultscoontroller从核心数据sqlite获取数据。它在过滤之前工作正常,但现在我需要能够点击一个按钮,让它只显示属性之一(aBOOL)为YES的对象。让我们称之为isfavorite 我有点不知道从哪里开始。我理解谓词的概念,我构建了这个谓词,它应该可以工作: NSPredicate *predicate = [NSPredicate predicateWithFormat: @"isFavourite

我正在尝试筛选
UITableView
中的对象,该视图通过
nsfetchedresultscoontroller
从核心数据sqlite获取数据。它在过滤之前工作正常,但现在我需要能够点击一个按钮,让它只显示属性之一(a
BOOL
)为
YES
的对象。让我们称之为
isfavorite

我有点不知道从哪里开始。我理解谓词的概念,我构建了这个谓词,它应该可以工作:

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"isFavourite == 1"];
但是,对于如何将该谓词附加到
NSFetchedResultsController
,我有点困惑。我已经分配并初始化了它,使用了一个单独的fetch请求,该请求只返回该实体的所有对象(这非常有效)。如果它已经初始化,我可以更改它的获取请求吗?如果是这样,我该怎么做,然后我该如何让它重新运行查询。然后是否需要使用
reloadData
或类似工具手动更新
UITableView
。那么,当我想关闭此过滤器并返回查看所有结果时,我该怎么办

我在这里读了很多现有的问题,但大多数似乎与搜索栏有关,这使得答案更加复杂。我也读过苹果的文档,但往往会发现它是以一种相当神秘的方式写的。下面是我的代码,我只完成了
filterFavourite
方法的一部分,这就是我寻求帮助和澄清的地方

- (NSFetchedResultsController *) fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

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

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey: @"quoteID" ascending: YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

    [fetchRequest setFetchBatchSize: 50];

    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest: fetchRequest managedObjectContext: [[FQCoreDataController sharedCoreDataController] managedObjectContext] sectionNameKeyPath: nil cacheName: nil];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

- (IBAction) filterFavourite: (id) sender
{
    if (isDisplayingFavourite) {
        // Switch to showing all..
        NSPredicate *predicate = [NSPredicate predicateWithFormat: @"isFavourite == 1"];

        isDisplayingFavourite = NO;
    } else {
        // Switch to showing favourites only..

        isDisplayingFavourite = YES;
    }

}

编辑:此代码中从未调用委托方法“
controllerDidChangeContent
”。我也不明白为什么会这样。非常,非常混乱,核心数据就像一堵砖墙。事实上,四个委托方法都没有被调用。

您没有将谓词附加到
NSFetchedResultsController
——而是将它附加到
NSFetchRequest
。它有一个名为
setPredicate:
的方法,该方法完全按照其名称执行


您可以通过更新
fetchRequest
属性并再次调用
performFetch:
来修改提取请求。您还可以取消
fetchedResultsController
ivar,并使上述代码足够灵活,以添加任何有用的谓词。下次调用
fetchedResultsController
方法时,它将使用当前谓词为您创建一个新实例。它将所有
NSFetchedResultsController
代码整合到一个方法中。它的CPU使用率可能稍高一些,但也可能更易于维护。

因此,当我使用完它后,无论我在哪里首先使用它,我都应该
nil
将其删除,然后当我在其他地方使用它时,我应该使用谓词创建一个新的
NSFetchRequest
,然后再次对其调用
performFetch
?我会修改
fetchedResultsController
,在必要时添加谓词,然后将实例变量置零。您可以将创建“获取结果”控制器的所有代码保留在一个方法中,只要您使其比现在灵活一点。@TomHarrington:我同意您的答案描述了最佳解决方案。-但是我对您的评论有一个问题:“无法更改NSFetchedResultsController上的获取请求”。NSFetchedResultsController文档中有一节“修改提取请求”,描述了如何为FRC设置新的提取请求。因此,您不能修改现有的获取请求(即更改谓词),但可以将新的获取请求分配给现有FRC。对吗?