Iphone 使用NSFetchedResultsController将UISegmentedController添加到导航栏

Iphone 使用NSFetchedResultsController将UISegmentedController添加到导航栏,iphone,cocoa-touch,core-data,nsfetchedresultscontroller,Iphone,Cocoa Touch,Core Data,Nsfetchedresultscontroller,我使用的是一个UITableView,它从NSFetchedResultsController获取数据。我想在我的导航栏中添加一个UISegmentedControl,在显示所有记录和仅显示带星号==YES的记录之间切换表格 我读过其他一些SO帖子,指出实现这一点的一种方法是创建第二个NSFetchedResultsController,它的NSPredicate带有starred==YES,但创建第二个NSFetchedResultsController似乎太过了 有更简单的方法吗?不是根据N

我使用的是一个
UITableView
,它从
NSFetchedResultsController
获取数据。我想在我的导航栏中添加一个
UISegmentedControl
,在显示所有记录和仅显示带星号==YES的记录之间切换表格

我读过其他一些SO帖子,指出实现这一点的一种方法是创建第二个
NSFetchedResultsController
,它的
NSPredicate
带有
starred==YES
,但创建第二个
NSFetchedResultsController
似乎太过了


有更简单的方法吗?

不是根据NSFetchedResultsController上的文档。如果查看fetchRequests属性的文档,您将看到以下注意事项:

重要提示:您不能修改 获取请求。例如,你必须 不更改其谓词或排序 订单

由于fetchRequest属性是只读的,因此唯一的选项是创建一个新的fetched results控制器

可能会更改谓词并使其正常工作,但通常情况下,做一些明显违背苹果在文档中所说内容的事情是不好的,因为这可能会在未来的版本中中断

而且,要小心过早的优化!除非您已经对其进行了测试,并发现创建一个全新的fetch results控制器是一个很大的性能消耗,否则不值得尝试以不推荐的方式进行操作

下面是如何在“获取结果”控制器上设置新谓词的。fetchedResultsController是我的视图控制器的一个属性。谓词是视图控制器的私有ivar

我已经有了按需创建fetched results控制器的所有代码,所以要设置谓词,只需删除缓存的一个即可

- (void)setPredicate:(NSPredicate *)newPredicate {
    predicate = [newPredicate copy];

    // Make sure to delete the cache
    // (using the name from when you created the fetched results controller)
    [NSFetchedResultsController deleteCacheWithName:@"Root"];

    // Delete the old fetched results controller
    self.fetchedResultsController = nil;

    // TODO: Handle error!
    // This will cause the fetched results controller to be created
    // with the new predicate
    [self.fetchedResultsController performFetch:nil];
    [self.tableView reloadData];
}
此代码基于样板文件XCode,在启动使用核心数据的项目时生成

- (NSFetchedResultsController *)fetchedResultsController {

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

    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:[MyEntity entityName] inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    [fetchRequest setFetchBatchSize:20];

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

    [fetchRequest setSortDescriptors:sortDescriptors];
    [fetchRequest setPredicate:predicate];

    // 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;
}

不是根据NSFetchedResultsController上的文档。如果查看fetchRequests属性的文档,您将看到以下注意事项:

重要提示:您不能修改 获取请求。例如,你必须 不更改其谓词或排序 订单

由于fetchRequest属性是只读的,因此唯一的选项是创建一个新的fetched results控制器

可能会更改谓词并使其正常工作,但通常情况下,做一些明显违背苹果在文档中所说内容的事情是不好的,因为这可能会在未来的版本中中断

而且,要小心过早的优化!除非您已经对其进行了测试,并发现创建一个全新的fetch results控制器是一个很大的性能消耗,否则不值得尝试以不推荐的方式进行操作

下面是如何在“获取结果”控制器上设置新谓词的。fetchedResultsController是我的视图控制器的一个属性。谓词是视图控制器的私有ivar

我已经有了按需创建fetched results控制器的所有代码,所以要设置谓词,只需删除缓存的一个即可

- (void)setPredicate:(NSPredicate *)newPredicate {
    predicate = [newPredicate copy];

    // Make sure to delete the cache
    // (using the name from when you created the fetched results controller)
    [NSFetchedResultsController deleteCacheWithName:@"Root"];

    // Delete the old fetched results controller
    self.fetchedResultsController = nil;

    // TODO: Handle error!
    // This will cause the fetched results controller to be created
    // with the new predicate
    [self.fetchedResultsController performFetch:nil];
    [self.tableView reloadData];
}
此代码基于样板文件XCode,在启动使用核心数据的项目时生成

- (NSFetchedResultsController *)fetchedResultsController {

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

    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:[MyEntity entityName] inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    [fetchRequest setFetchBatchSize:20];

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

    [fetchRequest setSortDescriptors:sortDescriptors];
    [fetchRequest setPredicate:predicate];

    // 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;
}

我只需要创建两个独立的FRC,并将它们分配给控制器的不同属性。然后,根据哪个切换处于活动状态,表将使用一个或另一个。我喜欢使用通用方法,即您可以更改谓词,其他一切都在后台处理。它甚至可以有多个FRC实例,并根据谓词交换它们……我只需要创建两个单独的FRC,并将它们分配给控制器的不同属性。然后,根据哪个切换处于活动状态,表将使用一个或另一个。我喜欢使用通用方法,即您可以更改谓词,其他一切都在后台处理。它甚至可以有多个FRC实例,并根据谓词交换它们。。。。