tableView:cellForRowAtIndexPath删除项目后用nil indexPath调用

我有一个UITableViewpipe理的相当香草的UITableView来显示给定的核心数据实体的所有实例。

当用户通过滑动删除表视图中的一个条目时, tableView:cellForRowAtIndexPath:最终会在我的UITableViewController用一个nil indexPath 。 由于我没有预料到它将被调用一个nil indexPath ,应用程序崩溃。

我可以通过检查nil值来解决崩溃问题,然后返回一个空单元格。 这似乎有效,但我仍然担心我可能处理了错误的事情。 有任何想法吗? 有没有人见过tableView:cellForRowAtIndexPath:nil indexPath

请注意,这只有当用户通过滑过单元格从表视图中删除时才会发生。 使用表格视图编辑模式删除项目时,不会发生。 删除单元格的两种方法会有什么不同?

那么,在表视图委托方法中获得一个nil indexPath真的是一个好的情况吗?

我的视图控制器代码是非常标准的。 这里是删除:

 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath]; [self.moc deleteObject:managedObject]; NSError *error = NULL; Boolean success = [self.moc save:&error]; if (!success) { <snip> } // actual row deletion from table view will be handle from Fetched Result Controller delegate // [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else { <snip> } } 

这将导致调用NSFetchedResultsController委托方法:

 - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeDelete: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeInsert: <snip> break; case NSFetchedResultsChangeUpdate: <snip> break; case NSFetchedResultsChangeMove: <snip> break; } } 

当然,数据源方法由NSFetchedResultsController处理,例如:

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; return [sectionInfo numberOfObjects]; } 

非常感谢。

看起来好像你是从表中删除indexPath,但表数据源不更新。 您是否通过NSFetchedResultsController正确更新了表数据源来validation数据源的分布过程?

我会这样做,因为你直接从托pipe上下文中填充表,为什么不删除首先从托pipe上下文中删除对象,然后使用reloadData立即更新上下文中的表。 但使用你的方法,我认为你需要添加beginUpdatesendUpdates

 #pragma mark - #pragma mark Fetched results controller delegate - (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]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { UITableView *tableViews = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: [tableViews insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [tableViews deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: [_delegate configureCell:[tableViews cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; break; case NSFetchedResultsChangeMove: [tableViews deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableViews insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:NO]; } 

我在表视图中使用CoreData,并允许用户删除logging和更新他们,我有他们在4个应用程序没有遇到你提到的问题。

我的代码中有这些FetchedResultsController委托方法

  - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { // The fetch controller is about to start sending change notifications, so prepare the table view for updates. [self.myTableView beginUpdates]; } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { // The fetch controller has sent all current change notifications, so tell the table view to process all updates. [self.myTableView endUpdates]; 

}