由于自引用连接,从UITableView删除时应用程序崩溃

时间:2010-10-19 23:26:46

标签: iphone uitableview core-data

我是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来解决这个问题:但我不相信这是处理这个问题的正确方法。

我感谢任何人都可以提供帮助。

2 个答案:

答案 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部分。这让我不会崩溃。