Ios NSFetchedResultsController controllerDidChangeContent方法中的无限循环

Ios NSFetchedResultsController controllerDidChangeContent方法中的无限循环,ios,uitableview,core-data,nsfetchedresultscontroller,infinite-loop,Ios,Uitableview,Core Data,Nsfetchedresultscontroller,Infinite Loop,我有UITableViewController表,并使用nsfetchedresultscoontroller从核心数据中提取行。我的tableView负责分层数据。Eatch行位置表示层(在零行最高层,n行最低层)。假设我们有一个名为Layers*Layers的对象。当我创建新层时,它需要转到表中的第一行(indexPath.row==0),并需要获得layers.layer.position=0)。当我创建新层或进行一些其他更改(移动、删除)时,我需要刷新核心数据对象层(每个层需要获得新的位

我有
UITableViewController
表,并使用
nsfetchedresultscoontroller
从核心数据中提取行。我的
tableView
负责分层数据。Eatch行位置表示层(在零行最高层,n行最低层)。假设我们有一个名为
Layers*Layers
的对象。当我创建新层时,它需要转到表中的第一行(
indexPath.row==0
),并需要获得
layers.layer.position=0
)。当我创建新层或进行一些其他更改(移动、删除)时,我需要刷新核心数据对象
(每个层需要获得新的位置值)。但如果我通过调用
[self updateLayersPosition]
方法来刷新层位置,它将进入无限循环,因为每次旧层值更改时,它都会一次又一次地返回相同的
controllerdChangeContent
方法。因此,问题是如何将表行或获取的控制器
indexPath.row
layers.layer.position
进行“绑定”?也许我可以知道如何停止
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];
}
-(void)更新层{
对于(int i=0;i<[self.tableView numberofrowsin节:0];i++){
nsindepath*indepath=[nsindepath indexPathForRow:i
不安全:0];
((Layer*)[self.fetchedResultsController对象索引路径:indexPath]).Layer.position=i;
}
}
-(void)controllerDidChangeContent:(NSFetchedResultsController*)控制器
{
[自我更新人员];
[self.tableView endUpdates];
}

修改核心数据对象后,将调用
NSFetchedResultsControllerDelegate
中的所有
willChange
/
didChange
方法。因此,如果您在
controllerDidChangeContent:
内修改任何
NSManagedObject
,它将再次触发
controllerDidChangeContent:
,导致无限循环

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

  • NSManagedObjects
  • 保存
    NSManagedObjectContext
  • NSFetchedResultsControllerDelegate
    的方法中:更新
    UITableView
    以反映更改(添加、重新加载、删除表视图行)
所以你可能想做这样的事情:

//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
将根据需要将层的位置“绑定”到表中的行(我假设您在提取请求中使用的排序描述符中使用了
position
属性)。如果您按照中的建议实现这些
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];
}

你不能在
controllerDidChangeContent:
中对你的上下文执行任何更改,这显然会导致无限循环。因此,在哪里调用该方法是安全的?取决于你如何编程你的应用程序。虽然不在这里。但如果我想让UITableViewController负责“分层”,那么就不需要我的代码如果我在layers对象中添加新的layer,这将是一件好事,这个UITableViewController类为我进行分层。那么,我需要使用NSFetchedResultsController或UITableViewController的什么方法来更改layers.layer.position值和indexPath.row值的依赖关系?我按照你说的做了,我在addLayer met中实现了所有代码霍德,现在分层工作!谢谢。