2012-07-30 52 views
-1

我在iPhone应用程序中设置了父子核心数据关系。我有一个Manufacturer对象和一个Car对象。这与作为所有者的制造商是多对多的关系。主视图是包含制造商的表格视图。详细视图是不同类型汽车的另一个​​表格视图。我一直在使用Tim Roadley's Core Data Tutorial作为基础。本教程使用Stanford's Core Data Table View Library作为表格视图。核心数据表视图删除崩溃

增加汽车制造商,并给了我没有问题,但是当我去和删除多辆在表视图中我得到这个错误:

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:1037 

2012-07-29 23:39:33.561应用[16368:c07] *由于未捕获异常'NSInternalInconsistencyException',原因:'无效更新:无效的行数在部分0中。更新后(0)的现有节中包含的行数必须相等到更新之前该部分中包含的行数(2),加上或减去从该部分插入或删除的行数(0插入,1删除)以及正数或负数ows移入或移出该部分(0移入,0移出)。'

如果我删除了唯一的汽车,它工作得很好,直到我尝试添加一个新的车,当我得到这个错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Illegal attempt to establish a relationship 'manufacturer' between objects in different contexts (source = <Car: 0x6d96da0> (entity: Car; id: 0x6d8a3c0 <x-coredata:///Car/tC78E17EB-1D68-4998-8C4D-6D1199CE253F4> ; data: { 
dateAdded = nil; 
manufacturer = nil; 
carName = new; 
}) , destination = <Manufacturer: 0x6bb1f40> (entity: Manufacturer; id: 0x6d87340 <x-coredata://2E8DDF34-B01A-4203-A53E-73DBE6A2F976/Garden/p6> ; data: <fault>))' 

这里是我的编辑方法:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

if (editingStyle == UITableViewCellEditingStyleDelete) { 

    [self.tableView beginUpdates]; 

    Plant *plantToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    NSLog(@"Deleting plant '%@'", plantToDelete.plantName); 
    [self.managedObjectContext deleteObject:plantToDelete]; 
    [self.managedObjectContext save:nil]; 

    //delete empty tableview row 
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight]; 
    NSLog(@"Before performFetch..."); 
    [self performFetch]; 
    NSLog(@"After performFetch..."); 

    [self.tableView endUpdates]; 
} 
} 

performFetch方法包含在前面提到的CoreDataTableViewController文件中。为了您的方便,那就是:

(void)performFetch 
{ 
_debug = YES; 

if (self.fetchedResultsController) { 
    if (self.fetchedResultsController.fetchRequest.predicate) { 
     if (self.debug) NSLog(@"[%@ %@] fetching %@ with predicate: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate); 
    } else { 
     if (self.debug) NSLog(@"[%@ %@] fetching all %@ (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName); 
    } 
    NSError *error; 
    [self.fetchedResultsController performFetch:&error]; 
    if (error) NSLog(@"[%@ %@] %@ (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]); 
} else { 
    if (self.debug) NSLog(@"[%@ %@] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); 
} 
[self.tableView reloadData]; 

}

根据其他的问题,我用beginUpdatesendUpdates正确地这样做。这是一个令人困惑的错误。谢谢你的帮助。

回答

1

我不知道为什么你再次执行提取,如果一个对象从上下文中删除,提取的结果控制器已经知道这种变化。我认为你遇到的主要问题是在处理表更新的过程中调用执行提取。如果你评论这条线,它是否仍然有错误?

此外,以下可能会或可能不会是问题的另一部分,因为这是你在哪里我自己的代码不同:

我还没有看到开始/结束编辑中的tableView电话:CommitEditingStyle:之前。该方法中我自己的进程通常会删除对象,而不用担心表格行。表行的对帐fetchedResultController委托方法如下所示:

-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
    //the fetch controller is about to start sending change notifications so prepare the tableview 
    [self.tableView beginUpdates]; 
} 


-(void)controller:(NSFetchedResultsController *)controller 
    didChangeObject:(id)anObject 
     atIndexPath:(NSIndexPath *)indexPath 
    forChangeType:(NSFetchedResultsChangeType)type 
    newIndexPath:(NSIndexPath *)newIndexPath { 

    // reconcile your rows here 
    switch(type) { 
    case NSFetchedResultsChangeInsert: 

     break; 

    case NSFetchedResultsChangeDelete: 
     // this one is you 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight]; 
     break; 

    case NSFetchedResultsChangeUpdate: 

     break; 

    case NSFetchedResultsChangeMove: 

     break; 
} 

-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates. 
    [self.tableView endUpdates]; 
} 

只要行数相匹配获取的对象毕竟这个数字,你不应该有错误。

+0

是的,在注释掉该行后,我仍然收到错误。 – Andrew 2012-08-04 21:06:14

+0

我下载了基于你的项目的项目。我看到你在这里的东西几乎与它相同。它在那里工作,虽然我看到几种模式对我来说毫无意义。如果您使用该项目作为基础,则应该查看自己的不同之处。错误消息提到“'非法尝试在不同情况下的对象之间建立关系'制造商'”。你有多个上下文吗?那肯定会做到。 – 2012-08-05 01:28:18

0

尝试删除线

//delete empty tableview row 
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight]; 
NSLog(@"Before performFetch..."); 
[self performFetch]; 
NSLog(@"After performFetch..."); 

我相信CoreDataTableViewController会自动处理从表中删除的行。你基本上删除了两次导致错误的行。

0

当我打开一个tableviewController,它是Tim Roadley的CoreDataTableViewController的子类时,发生了同样的错误。我的特定应用程序不需要用户添加或删除行,但它允许他们通过名称和距离重新排序获取的结果以及搜索数据。我用Dean David的答案(上面的答案),但在每个案例陈述后,我只添加了一个break语句。到目前为止,这个应用程序已经工作!