我是一个全新的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.
删除操作似乎能够正确生成 [0,0] 的 NSFetchedResultsChangeDelete,但接着又立即生成了一个 [0,1] 的 NSFetchedResultsChangeUpdate,而 [0,1] 在删除后已经不存在了,因为 [0,1] 看起来现在已经在 [0,0] 中了。
如果没有关联的 Connection 记录,它就可以被成功删除。
我似乎可以通过在 controllerDidChangeContent 中简单地调用 [self.tableView reloadData] 来解决这个问题,而不是实现 begin/end updates 和 didChangeOnject:,但我不认为这是处理这个问题的正确方式。
感谢任何人可以提供的帮助。