了解NSFetchedResultsController的工作原理

bub*_*les 5 iphone ios

首先,非常感谢你,如果你有时间帮助我!

我一直在学习NSFetchedResultsController并试图尽可能多地理解它,然而,有些事情让我非常困惑.这段代码来自我在网上找到的教程.基本上我有最简单的获取控制器设置与这样的真正花哨的方法

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            // Reloading the section inserts a new row and ensures that titles are updated appropriately.
            [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

 (NSFetchedResultsController *)fetchedResultsController {

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

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

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] 
        initWithKey:@"details.closeDate" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:20];

    NSFetchedResultsController *theFetchedResultsController = 
        [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
            managedObjectContext:_context sectionNameKeyPath:nil 
            cacheName:@"Root"];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    [sort release];
    [fetchRequest release];
    [theFetchedResultsController release];

    return _fetchedResultsController;    

}
Run Code Online (Sandbox Code Playgroud)
  1. 我是否需要每次为不同的视图控制器创建一个新的获取控制器?例如,如果我在一个列表视图中有一个企业列表.然后我点击其中一个,使我对员工的名单在ocmpany,我必须使用不同的fetchedViewController,因为我需要重新指定实体键吧?见上文我的实现.

  2. 使用我当前的实现,它非常适合列出项目.假设我有一个名为VC的视图控制器.我完全实现了NSFetchedResultsController.我有一个barbutton添加项目和一个方法addButtonPressed,当按下模态时添加一个视图(从下往上).在这个相同的方法,我有 Entity myEntity = [NSEntityDescription insertNNewObjectForEntityForName:@"Entity" inManagedObjectContext:context_];然后我告诉代码进入另一个视图.但是,当动画向上移动新的导航控制器时,新单元格已经显示自己的动画中期.根据我的理解,这两个方法 - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath - (UITableViewCell *)tableView:(UITableView *)tableView 上面的代码片段中的前两个方法一起被调用.我该怎么办呢?我想要在当前视图中显示任何内容,直到我通过转到另一个视图添加新实体.第二个另一个对象被调用到上下文中,更新方法必须被调用或者其他东西

  3. 这段代码的作用是什么?特别是id <stuff>的部分

    (void)controller:(NSFetchedResultsController*)controller didChangeSection:(id NSFetchedResultsSectionInfo)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
    
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    编辑:神圣$#$,格式化令人沮丧.在上面的代码中应该有didChangeSection:(id(少于等于标志)NSFetchedResultsSectionInfo(大于等号))

4我在哪里可以了解更多相关信息.即各个内容更新方法的作用以及调用它们的时间等.另外NSFetchedResultcontroller是否作为单个数组?这意味着如果我想要一个包含多个部分的tableview,我需要更多的ViewControllers?再次感谢!

Rob*_*oth 4

我赞同布拉德的评论,但我会给你一些建议:

  1. 基本上是的,您需要为每个要查询的实体一个新的 NSFetchedResultsController 。但是,您根本不需要使用 NSFetchedResultsController,这只是一个很好的类,可以让您像在问题#2 中所做的那样使用 tableView 做一些奇特的事情。

  2. 这里的问题是,您[NSEntityDescription insertNNewObjectForEntityForName:@"Entity" inManagedObjectContext:context_];从 tableViewController 进行调用,一旦您调用 NSFetechedResultsController 将收到一条消息,说明已插入一行,从而触发方法中的 NSFetchedResultsChangeInsert 路径controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:。NSFetchedResultsController 是一个对象,它监视从 CoreData 获取的数据是否有任何更改,然后让您能够在更改发生时执行操作。要解决显示问题,只需将 insertNewObjectForEntityName 调用移动到下一个 viewController 中,神奇的是,当您关闭该 viewController 时,您将拥有一个新行。

  3. NSFetchedResultsController 的 didChangeSection: 委托方法会通知您是否已从数据集中添加或删除了某个部分。请参阅我对#4 的回答,这一点应该很清楚。

  4. NSFetechedResultsController 允许您使用 init 调用的sectionNameKeyPath: 部分来“分段”它获取的数据。通过提供实体中数据点的名称,您可以将数据分组为多个部分。因此,回到 #3 和 #2,如果您碰巧在初始化 NSFetchedResultsController 时指定的“section”键路径中插入了一个具有新值的新实体,您将调用 didChangeSection: 委托。

我建议阅读 Apple 关于NSFetchedResultsControllerCoreData的文档,可能还有他们的TableView 编程指南。不要忘记下载并使用示例代码,在大多数情况下它比文档中的理论更容易理解。