我有 UITableViewController
表并使用 NSFetchedResultsController
从 Core Data 获取行。我的 tableView
负责分层数据。每个行位置代表层(在零行最高层,n - 最低行)。假设我们有一个名为 Layers *layers
的对象。当我创建新层时,它需要转到表中的第一行(indexPath.row == 0
)并且需要获取layers.layer.position = 0
。当我创建新层或进行一些其他更改(移动、删除)时,我需要刷新核心数据对象 layers
(每个层都需要获取新的位置值)。但是,如果我通过调用 [self updateLayersPosition]
方法在 controllerDidChangeContent
方法旁边刷新图层位置,它会进入无限循环,因为每次在每个旧图层值更改时它都会返回相同的 controllerDidChangeContent
方法一次又一次。所以问题是如何将表格行或获取的 Controller indexPath.row
与 layers.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)controllerDidChangeContentNSFetchedResultsController *)controller
{
[self updateLayers];
[self.tableView endUpdates];
}
NSFetchedResultsControllerDelegate
中的所有willChange
/didChange
方法都是在你修改Core Data 对象后调用的。所以如果你修改了controllerDidChangeContent:
里面的任何NSManagedObject
,都会再次触发controllerDidChangeContent:
,导致死循环。
您可以将这些委托(delegate)回调视为一个 Controller ,说“您已经更改了 Core Data 模型中的某些内容,现在让我们更新 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
}
关键是添加新层后立即更新每一层的position
,然后保存上下文。然后 NSFetchedResultsController
将按照您的需要将图层的位置“绑定(bind)”到表中的行(我假设您在使用的排序描述符中使用 position
属性在获取请求中)。如果您按照 documentation 中的建议实现这些 NSFetchedResultsControllerDelegate
方法,它应该做的工作:
- (void)controllerWillChangeContentNSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controllerNSFetchedResultsController *)controller didChangeObjectid)anObject
atIndexPathNSIndexPath *)indexPath forChangeTypeNSFetchedResultsChangeType)type
newIndexPathNSIndexPath *)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)controllerDidChangeContentNSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
关于ios - NSFetchedResultsControllers controllerDidChangeContent 方法中的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25103478/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |