我是iPhone开发的新手(这里发布的第一个问题),并且有点像核心数据和表格视图。
简而言之,当我从UITableView中删除一行时,我的应用程序崩溃了,因为NSFetchedResultsChangeUpdate在由于自引用表上的级联删除而已被删除的记录上被调用。
以下是数据模型的说明:
有两个实体; 人 和 连接 。
人员 包含名称(字符串),连接(与 的多人关系连接 - >来源,级联删除规则)和 connectedby (与多人关系 连接 - >连接,级联删除规则)
连接 包含关系(字符串),来源(与 人<的关系< / strong> - &gt;连接,取消删除规则)和连接(与 人的关系 - >&gt; connectedby ,nullify删除规则)
这个想法是有两个人通过关系连接(例如母亲或儿子)
在我的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]中不再存在删除后。
如果没有关联的连接记录,则删除正常。
我似乎只是通过在controllerDidChangeContent上调用[self.tableView reloadData]而不是实现begin / end updates和didChangeOnject来解决这个问题:但我不相信这是处理这个问题的正确方法。
我感谢任何人都可以提供帮助。
答案 0 :(得分:2)
我通过向 NSFetchedResultsController (在 initWithFetchRequest 中)提供非零 sectionNameKeyPath 来解决类似的问题。
然后我使用以下方法避免了部分:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return @"";
}
非常讨厌。
仅供参考,我的问题是这个错误:
严重的应用程序错误。一个 从代表处捕获了异常 NSFetchedResultsController期间的一个 调用-controllerDidChangeContent:。 * - [NSMutableArray objectAtIndex:]:索引0超出空数组的边界 with userInfo(null)
答案 1 :(得分:0)
在(void)controller:(NSFetchedResultsController *)controller didChangeObject
的顶部:我正在从fetchedResultsController
中取出实体。好吧,当你刚刚删除了对象并需要更新表时,这真的搞砸了。我将实体提取移动到NSFetchedResultsChangeUpdate
部分。这让我不会崩溃。