2012-07-30 50 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語句。到目前爲止,這個應用程序已經工作!