主细节应用程序-
我有一个由NSFetchedResultsController
及其委托方法管理的UITableViewController
。在表视图的第一部分中,我还有一个额外的单元格,其中有一个UIWebView
,用于显示嵌入的视频。此单元格不是NSFetchedResultsController
的一部分。当调用-tableView cellForRowAtIndexPath
时,我将其添加到IF
语句中,该语句会检查它是否是第一节和第一行。大多数情况下,一切都很好。我可以选择一行并将其显示在DetailViewController
中,我可以从tableView
中删除项目,我可以更改DetailViewController
中的信息,tableViewCell
标签更新不会出现任何问题。
我的问题
我唯一一次对它的设置方式有问题是,当我从tableView
的第一个部分删除最后一个对象时。
错误
CoreData:错误:严重的应用程序错误。捕获到异常在调用期间从NSFetchedResultsController的委托-controllerIDChangeContent:。无效更新:节0中的行数无效。现有节中包含的行数更新之后(3)必须等于中包含的行数更新之前的部分(2),加上或减去行数插入或从该节删除(0插入,0删除),加上或减去移入或移出该节的行数(已移动0在,0移出)。带userInfo(null)
代码
行数部分
这是我检查视频是否可用以及部分是否为0返回1行的地方。否则返回来自CCD_ 12的对象计数。我想这就是我的问题所在。然而,我不知道如何解决它。因为我用NSFetchedResultsController
委托方法管理它,所以在switch语句中的"type"中有什么可以做的吗?
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0 && self.videoInfoReceived == YES) {
id <NSFetchedResultsSectionInfo> secInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [secInfo numberOfObjects] + 1;
} else {
id <NSFetchedResultsSectionInfo> secInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [secInfo numberOfObjects];
}
}
NSFetchedResultsController委派
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
NSLog(@"didChangeSection - ChangeInsert");
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
NSLog(@"didChangeSection - ChangeDelete");
break;
}
}
- (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:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
NSLog(@"didChangeObject - ChangeInsert");
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
NSLog(@"didChangeObject - ChangeDelete");
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
NSLog(@"didChangeObject - ChangeUpdate");
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
NSLog(@"didChangeObject - ChangeMove");
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
您需要更多的条件代码来检查发送的任何索引路径是否用于第一个(零)部分。如果是,则FRC被赋予了"错误"的行号,因为您已经告诉表视图一个行数,而FRC理解不同的行数。
基本上,只要您从表视图接收到索引路径,请检查该节(如果是== 0
),使用相同的节和row - 1
创建一个新的索引路径,并使用它来访问FRC中的对象。
相反,当您从FRC收到索引路径时,您需要row + 1
,然后才能使用它来要求表视图插入/删除/移动。
在您的问题中,您声明:
当我从表的第一部分删除最后一个对象时查看
这将使我期望例外情况说明以下内容(强调部分添加):
CoreData:错误:严重的应用程序错误。在调用-controllerIdChangeContent:期间,从NSFetchedResultsController的委托捕获到异常。无效更新:节0中的行数无效。更新(0)后现有节中包含的行数必须等于更新(1)前该节中所包含的行数来,加上或减去从该节插入或删除的行数(0插入,1删除),加上或减移入或移出该节的行数(0移入,0移出)。带userInfo(null)
因为异常状态表明行数从2增加到3,而没有添加任何行,所以我认为您的错误在模型层中,而不是在表视图代码中。你的表视图代码对我来说很好。