【发布时间】:2015-11-16 12:18:09
【问题描述】:
我有一个由 CoreData 支持的应用程序,它代表某种文件夹层次结构。
所以一个文件夹可以有一个子文件夹。
因此NSManagedObject关系父和子
服务器端目前仅支持两级层次结构。 主文件夹 -> 子文件夹。
但为了为未来做好准备,CoreData-Model 旨在支持无穷无尽的关卡。
所以关系是
parent <------>> children
文件夹还有一个属性name
因此,NSPredicate 的格式为 "parent != nil",NSFetchedResultsController 的格式为 parent.name sectionNameKeyPath
现在 FRC 将不包含空白部分(在此上下文中:没有子文件夹的文件夹)。我创建了一个默认子文件夹(这个文件夹在内部使用......所以我不会搞乱用户层次结构)。
如果用户创建一个新的主文件夹,我再次执行以下操作:
Folder * mainFolder = [self createNewFolderWithName:userSetName];
Folder * systemChildSubfolder = [self createNewFolderWithName:SYSTEM_SUBFOLDER_NAME];
[mainFolder addChildFolderObject:systemChildSubfolder];
[self saveContext];
这很好,但是当 FRC 的委托方法启动时,我会得到这个错误:
CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. attempt to insert row 0 into section 3, but there are only 0 rows in section 3 after the update with userInfo (null)
看来,FRC 偶然发现了新部分和插入的行。
但我还没有找到解决这个问题的方法。即使我在创建并保存了 mainFolder 之后创建并添加了systemChildSubfolder……我仍然会收到该错误。
FRC 似乎仍然返回旧的节数并尝试在错误的节中添加新行?
所以任何人都可以向我解释如何让 FRC 像我期望的那样工作: 先加节再加行?
FRC 代表:
#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[[self folderTableView] beginUpdates];
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch (type) {
case NSFetchedResultsChangeInsert:
[[self folderTableView] insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
return;
case NSFetchedResultsChangeDelete:
[[self folderTableView] deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
return;
default:
return;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
switch(type) {
case NSFetchedResultsChangeInsert:
[[self folderTableView] insertRowsAtIndexPaths:@[newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[[self folderTableView] deleteRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
{
UITableViewCell * tableViewCell = [[self tableView] dequeueReusableCellWithIdentifier:TableViewCellIdentifier forIndexPath:indexPath];
Folder * folder = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[self configureTableViewCell:tableViewCell withFolder:folder];
}
break;
case NSFetchedResultsChangeMove:
[[self folderTableView] insertRowsAtIndexPaths:@[newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
[[self folderTableView] deleteRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[[self folderTableView] endUpdates];
}
简短更新:
我怀疑 FRC 不会为新父级更新,尽管它有一个子文件夹。
但是新子节点的更新具有正确的 IndexPath(如果它的父节点在 FRC 中),但它与 FRC 中存储的内容不匹配。
【问题讨论】:
-
如果你想支持任意深度并允许用户向下钻取,为什么不是
"parent == nil"。您当前的界面不会显示层次结构,它将是一个非常大的分段列表......它还会避免您为管理创建的文件夹 -
行是子文件夹,它们确实有父文件夹。父文件夹将在这些部分中表示。一切正常且正确,问题出在 FRC 的某个地方,它是委托
-
但是当您添加第三个深度的文件夹时,它们也将显示为行,因此您的第 2 级行也将成为具有更多行的部分 - 这真的是您/用户想要的吗?
-
另外,您没有显示委托实现,或使用 FRC 的表委托,或列出崩溃前收到的更改
-
你说得对……但目前我们只有 2 个级别,因此可以有父级!=nil
标签: cocoa core-data nsfetchedresultscontroller nsfetchrequest