更新由 NSFetchedResultsController 管理并在第一部分有 1 个额外单元格的 UITableView
Posted
技术标签:
【中文标题】更新由 NSFetchedResultsController 管理并在第一部分有 1 个额外单元格的 UITableView【英文标题】:Updating UITableView that is managed by NSFetchedResultsController and has 1 extra cell in the first section 【发布时间】:2013-07-15 01:17:10 【问题描述】:主从申请 -
我有一个由NSFetchedResultsController
及其委托方法管理的UITableViewController
。我在 tableview 的第一部分还有一个额外的单元格,其中有一个 UIWebView
,它显示嵌入的视频。此单元格不是NSFetchedResultsController
的一部分。当调用-tableView cellForRowAtIndexPath
时,我将它添加到IF
语句中,以检查它是否是第一部分和第一行。在大多数情况下,一切都很好。我可以选择一行并在DetailViewController
中显示它,我可以从tableView
中删除项目,我可以更改DetailViewController
中的信息并且tableViewCell
标签更新没有任何问题。
我的问题
我唯一遇到的设置问题是,当我从tableView
的第一部分删除最后一个对象时。
错误
CoreData:错误:严重的应用程序错误。捕获到异常 在调用期间从 NSFetchedResultsController 的委托 -controllerDidChangeContent:。无效更新:第 0 节中的行数无效。现有节中包含的行数 更新后(3)必须等于包含的行数 更新前的那个部分(2),加减行数 从该部分插入或删除(0 插入,0 删除)和加上 或减去移入或移出该部分的行数(0 移动 入,0 移出)。与 userInfo (null)
代码
numberOfRowsInSection
我在这里检查视频是否可用,如果该部分为 0,则返回 1 个额外行。否则从NSFetchedResultsController
返回对象计数。我假设这是我的问题所在。但是,我不知道如何解决它。因为我有它由NSFetchedResultsController
委托方法管理,所以我可以在 switch 语句的“类型”内做些什么?
- (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];
【问题讨论】:
【参考方案1】:您需要更多条件代码来检查您发送的任何索引路径是否用于第一个(零)部分。如果是这样,则 FRC 被赋予了“错误”的行号,因为您已经告诉表视图一个行计数,而 FRC 理解的是不同的行数。
基本上,在您收到从表视图的索引路径的任何地方,检查该部分,如果是== 0
,则创建一个具有相同部分和row - 1
的新索引路径并使用它来访问 FRC 中的对象。
相反,当您收到来自 FRC 的索引路径时,您需要 row + 1
才能使用它来请求表格视图插入/删除/移动。
【讨论】:
我最初是通过检查 section == 0 来尝试的,然后创建/更新了 indexPath。最初对我不起作用。但是,自从我阅读了您的答案后,我决定回去再试一次。仅当我检查 section == 0 以及 [tableView numberOfRowsInSection:0] > 2 时才有效。我不知道为什么,但它有效。再次感谢【参考方案2】:在你的问题中你说:
当我从 tableView 的第一部分删除最后一个对象时
这会导致我期望异常声明以下内容(强调):
CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了异常。无效更新:第 0 节中的行数无效。现有节中包含的行数更新后 (0) 必须等于该节中包含的行数之前update (1),加或减从该部分插入或删除的行数(0 插入,1 删除),加或减移入或移出该部分的行数部分(0 移入,0 移出)。与 userInfo (null)
因为异常表明行数从 2 增加到 3 却没有添加任何行,所以我认为您的错误出现在模型层而不是表视图代码中。您的表格视图代码对我来说看起来很棒。
【讨论】:
当我说从表格视图的第一部分删除最后一个对象时,我并不是指下一部分之前的最底部对象。我的意思是当第一部分中有多个对象时,当我删除一个对象直到到达视频 webview 单元格之外的最后一个对象时,它工作正常。 我明白你的意思。您的获取结果控制器对您的附加 Web 视图单元格一无所知,因此当您从给定部分中删除最后剩余的行时,获取结果控制器期望行数从 1 减少到 0。异常状态的事实行数从 2 增加到 3 告诉我核心数据级别的删除操作的架构不正确。尝试完全注释掉您的自定义 Web 视图单元格,并使用一对一的表格视图单元格来正常删除 FRC 项目设置。 一旦工作正常,通过调整行数和 indexPath.row 值来添加额外的单元格,以从表格视图的索引中“转换”为获取结果中项目的索引.以上是关于更新由 NSFetchedResultsController 管理并在第一部分有 1 个额外单元格的 UITableView的主要内容,如果未能解决你的问题,请参考以下文章