ios - NSFetchedResultsController controllerDidChangeContent 方法中的无限循环

标签 ios uitableview core-data nsfetchedresultscontroller infinite-loop

我有 UITableViewController 表,并使用 NSFetchedResultsController 从核心数据中提取行。我的 tableView 负责分层数据。每行位置代表层(零行最高层,n 行最低层)。假设我们有名为 Layers *layers 的对象。当我创建新图层时,它需要转到表中的第一行(indexPath.row == 0)并需要获取layers.layer.position = 0。当我创建新图层或进行其他更改(移动、删除)时,我需要刷新核心数据对象图层(每个图层都需要获取新的位置值)。但是,如果我通过调用 controllerDidChangeContent 方法旁边的 [self updateLayersPosition] 方法来刷新图层位置,则会进入无限循环,因为每次旧图层值更改时,它都会返回相同的 controllerDidChangeContent 方法一次又一次。所以问题是如何将表行或获取的 Controller indexPath.rowlayers.layer.position“绑定(bind)”?也许我可以知道如何阻止 fetchedresultscontroller 获取,进行更新,然后再次开始获取?或者也许还有其他方法可以做到这一点?

这是代码:

-(void)updateLayers{
    for (int i = 0; i < [self.tableView numberOfRowsInSection:0]; i++) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i 
                                                    inSection:0];
            ((Layer *)[self.fetchedResultsController objectAtIndexPath:indexPath]).layer.position = i;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self updateLayers];
    [self.tableView endUpdates];
}

最佳答案

NSFetchedResultsControllerDelegate 中的所有 willChange/didChange 方法都会在修改 Core Data 对象后调用。因此,如果修改 controllerDidChangeContent: 中的任何 NSManagedObject,都会再次触发 controllerDidChangeContent:,从而导致无限循环。

您可以将这些委托(delegate)回调视为一个 Controller ,它表示“您已经更改了核心数据模型中的某些内容,现在让我们更新 UI(UITableView)。您应该遵循的一般模式是:

  • NSManagedObjects 中进行一项或多项更改(添加、修改、删除)
  • 保存NSManagedObjectContext
  • NSFetchedResultsControllerDelegate 的方法中:更新 UITableView 以反射(reflect)更改(添加、重新加载、删除 TableView 行)

所以你可能想做类似的事情:

//in the method in which you add a new Layer object
- (void)addLayer {
  Layer *layer = [NSEntityDescription insertNewObjectForEntityForName:@"Layer" inManagedObjectContext:context];
  //recalculate the position of all the other layers
  //save NSManagedObjectContext
}

关键是添加新层后立即更新每个层的位置,然后保存上下文。然后 NSFetchedResultsController 将根据您的需要将层的位置“绑定(bind)”到表中的行(我假设您在使用的排序描述符中使用 position 属性在获取请求中)。如果您按照 documentation 中的建议实现这些 NSFetchedResultsControllerDelegate 方法,它应该完成这项工作:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [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];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

关于ios - NSFetchedResultsController controllerDidChangeContent 方法中的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25103478/

相关文章:

iphone - 如何调用 - (BOOL)应用程序 :(UIApplication *)application handleOpenURL:(NSURL *)url from another class

ios - 只运行一次 CAEmitterLayer

ios - 放弃所有更改后,Xcode 删除 pod 文件夹和架构

iOS - 解包可选值时意外发现 nil

iphone - 自定义 uitableviewCell 导出返回 nil

ios - 创建新的核心数据模型

ios - 私有(private)数据库和订阅的 Cloudkit 问题?

swift - Firebase ChildrenCount 计入 tableview 标签

objective-c - 如何检查实体是否已存在于持久存储中

database - 迁移 CoreData 中的实体父级