Cocoa 不能同时添加子对象和父对象

Cocoa 不能同时添加子对象和父对象,cocoa,core-data,nsfetchedresultscontroller,nsfetchrequest,Cocoa,Core Data,Nsfetchedresultscontroller,Nsfetchrequest,我有一个CoreData支持的应用程序,它代表某种文件夹层次结构 因此文件夹可以有一个子文件夹 因此,NSManagedObject父对象和子对象之间的关系 服务器端目前只支持两级层次结构。 主文件夹->子文件夹 但为了为未来做好准备,CoreData模型旨在支持无限量的级别 所以这种关系是 parent <------>> children 这很好,但当FRC的委托方法启动时,我将得到以下错误: CoreData: error: Serious application er

我有一个CoreData支持的应用程序,它代表某种文件夹层次结构

因此文件夹可以有一个子文件夹

因此,
NSManagedObject
父对象和子对象之间的关系

服务器端目前只支持两级层次结构。 主文件夹->子文件夹

但为了为未来做好准备,CoreData模型旨在支持无限量的级别

所以这种关系是

parent <------>> children
这很好,但当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在新的部分和插入的行上绊倒了。 但我还没有找到解决这个问题的办法。即使我在创建并保存主文件夹后创建并添加了
systemChildSubfolder
,我仍然会遇到这个错误。 似乎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];
}
#pragma标记-NSFetchedResultsControllerDelegate
-(void)controllerWillChangeContent:(NSFetchedResultsController*)控制器{
[[self folderTableView]开始更新];
}
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeSection:(id)sectionInfo atIndex:(nsInteger)ChangeType的sectionIndex:(NSFetchedResultsChangeType)类型
{
开关(类型){
案例NSFetchedResultsChangesInsert:
[[self-folderTableView]insertSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
返回;
案例NSFetchedResultsChangeDelete:
[[self-folderTableView]deleteSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
返回;
违约:
返回;
}
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeObject:(id)一个对象
atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)类型
newindepath:(nsindepath*)newindepath
{
开关(类型){
案例NSFetchedResultsChangesInsert:
[[self-folderTableView]InsertRowsatindExpath:@[newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeDelete:
[[self-folderTableView]DeleteRowsatindExpath:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
打破
案例NSFetchedResultsChangeUpdate:
{
UITableViewCell*tableViewCell=[[self tableView]dequeueReusableCellWithIdentifier:TableViewCellIdentifier for indexPath:indexPath];
Folder*Folder=[[self-fetchedResultsController]objectAtIndexPath:indexPath];
[自配置tableViewCell:tableViewCell with folder:folder];
}
打破
案例NSFetchedResultsChangeMove:
[[self-folderTableView]InsertRowsatindExpath:@[newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
[[self-folderTableView]DeleteRowsatindExpath:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
打破
}
}
-(void)controllerDidChangeContent:(NSFetchedResultsController*)控制器
{
[[self-folderTableView]EndUpdate];
}
简短更新:

我的怀疑是,尽管FRC有一个childfolder,但它并没有为新的家长更新

但新子级的更新具有正确的IndexPath(如果其父级在FRC中),但与FRC中存储的内容不匹配。

2级 正如评论中所指出的,您的设置在两个以上的级别是不可行的。因为您只想处理父项和子项,所以我推荐以下简单的解决方案:

创建两个实体,
main文件夹
子文件夹
。如果愿意,您可以有一个
文件夹
类型的抽象父实体,但这并不是绝对必要的

MainFolder (subFolders) <------>> (mainFolder) SubFolder
MainFolder(子文件夹)>(MainFolder)子文件夹
获取
子文件夹
并使用
main文件夹
作为` sectionNameKeyPath'

就这样,再简单不过了


无限级 如果您想要实现一个潜在的无限层次结构,那么您可能应该在这个设置开始工作后问一个新问题

提示:您只有一种实体,
文件夹
,它也有一个属性
级别
。创建文件夹并设置父级
时,您需要检查
级别
,并将自己的
级别设置为父级的级别加一。层次结构上下的关系是自反的,即引用相同的
文件夹
实体


在FRC中,您将获取不带
sectionNameKeyPath
的父项(通过基于级别的谓词),对节使用
objectAtIndexPath
,并根据
文件夹填充节下面的行。子项
位于相应的表视图
数据源
方法中(
numberOfRowsInSection
cellforrowatinexpath
)。

为什么它不是
“parent==nil”
如果您希望支持任意深度,并允许用户向下搜索。您当前的界面不会显示层次结构,它将是一个非常大的分区列表……它还可以避免您为管理创建的文件夹。行是子文件夹,它们确实有父文件夹。父文件夹将在分区中表示。这就是l工作正常,正确,问题出在FRC的某个地方,它被授权了,但是当你添加第三个深度的文件夹时
MainFolder (subFolders) <------>> (mainFolder) SubFolder