由于自引用连接,从 UITableView 删除时应用程序崩溃
Posted
技术标签:
【中文标题】由于自引用连接,从 UITableView 删除时应用程序崩溃【英文标题】:App is crashing when deleting from UITableView due to self referencing connection 【发布时间】:2010-10-19 23:26:45 【问题描述】:我是 iPhone 开发的新手(以及此处发布的第一个问题),并且有点坚持使用 Core Data 和 Table Views。
简而言之,当我从 UITableView 中删除一行时,我的应用程序崩溃了,因为 NSFetchedResultsChangeUpdate 对由于自引用表上的级联删除而已被删除的记录调用。
这里是数据模型的描述:
有两个实体; Person 和 Connection。
Person 包含 name(字符串)、connections(与 的多个关系Connection->source,级联删除规则)和connectedby(与Connection->connection的多关系,级联删除规则)
Connection 包含 relationship(字符串)、source(与Person->connections,使删除规则无效)和connection(与Person->connectedby的关系,使删除规则无效)
这个想法是有两个人通过关系联系在一起(例如母亲或儿子)
在我的 TableViewController 中,我实现了以下内容:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
[self.tableView beginUpdates];
和
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
UITableView *tableView = self.tableView;
Person *person = nil;
switch(type)
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
person = (Person *)[fetchedResultsController objectAtIndexPath:indexPath];
[self configureCell:(PersonTableViewCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
person = (Person *)[fetchedResultsController objectAtIndexPath:indexPath];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
和
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
[self.tableView endUpdates];
以下是我创建的用于测试的示例记录:
Person *person1 = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
[person1 setName:[NSString stringWithFormat: @"Tommy"]];
Person *person2 = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
[person2 setName:[NSString stringWithFormat: @"Jane"]];
Connection *connection = [NSEntityDescription insertNewObjectForEntityForName:@"Connection" inManagedObjectContext:managedObjectContext];
[connection setConnection:person2];
[connection setSource:person1];
[connection setRelationship:[NSString stringWithFormat:@"Mother"]];
Connection *connection2 = [NSEntityDescription insertNewObjectForEntityForName:@"Connection" inManagedObjectContext:managedObjectContext];
[connection2 setConnection:person1];
[connection2 setSource:person2];
[connection2 setRelationship:[NSString stringWithFormat:@"Son"]];
当我删除 indexPath[0,0] 处的记录时,即本例中的 Jane,因为视图是按名称排序的,我生成以下错误:
2010-10-19 16:09:01.461 HelpMe[6324:207]
Serious application error.
Exception was caught during Core Data change processing.
This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.
*** -[NSMutableArray objectAtIndex:]: index 1 beyond bounds [0 .. 0] with userInfo (null)
Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
_Unwind_Resume called from function -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] in image CoreData.
删除似乎为 indexPath [0,0] 正确生成了 NSFetchedResultsChangeDelete,但随后也立即为 [0,1] 生成了 NSFetchedResultsChangeUpdate ,因为 [0,1] 现在似乎在 [0,0] 中,因此不再存在删除后。
没有关联的Connection记录,删除就好了。
我似乎可以通过简单地在 controllerDidChangeContent 上调用 [self.tableView reloadData] 而不是实现开始/结束更新和 didChangeOnject 来解决这个问题:但我不认为这是处理这个问题的正确方法。
感谢任何人提供的任何帮助。
【问题讨论】:
【参考方案1】:我通过向 NSFetchedResultsController(在 initWithFetchRequest 中)提供非零 sectionNameKeyPath 解决了类似的问题。
然后我使用以下方法避开了部分:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
return @"";
很烦人。
仅供参考,我的问题是这个错误:
严重的应用程序错误。一个 从委托中捕获了异常 NSFetchedResultsController 在一个 调用 -controllerDidChangeContent:。 * -[NSMutableArray objectAtIndex:]:空数组的索引 0 超出范围 与 userInfo (null)
【讨论】:
这让我非常头疼 - TY :)【参考方案2】:在 - (void)controller:(NSFetchedResultsController *)controller didChangeObject
的顶部:我正在从 fetchedResultsController
中提取实体。好吧,当您刚刚删除对象并需要更新表时,这确实会搞砸事情。我将实体提取移动到NSFetchedResultsChangeUpdate
部分。这让我没有崩溃。
【讨论】:
以上是关于由于自引用连接,从 UITableView 删除时应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章