2011-10-04 53 views
1

我在表視圖中使用核心數據模型時遇到問題。在表視圖的commitEditingStyle:委託方法我先刪除該模型的對象,然後將相應的行表視圖,與此類似:核心數據:什麼時候是deleteObject:完成?

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

{ 
    if (editingStyle == UITableViewCellEditingStyleDelete) { 
     [self.managedObjectContext deleteObject:[self coreDataObjectAtIndex:indexPath.row]; 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

但是,這引發了一個NSInternalInconsistencyException在UITableView的,因爲numberOfRowsInSection:委託方法返回由於核心數據對象尚未被刪除,所以錯誤的行數。

我該如何解決這種「官方方式」?或者最好的方法?

  1. 我一定要跟蹤NSManagedObjectContextObjectsDidChangeNotification通知,並等待相應的刪除通知?這是可行的,但可以quiclky變得相當混亂。

  2. 我只是等待,希望它在一段時間後被刪除?我測試過插入[self performSelector:withObject:afterDelay:]來延遲刪除表視圖行。即使延遲爲0.0,它也可以工作。我假定Core Data框架在當前運行循環完成後刪除對象,但這是有保證的嗎?它可能只是純粹的巧合。

  3. 處理這種情況的方法有哪些?對於像deleteObject:withCompletionHandler:這樣的塊完成API來說會更好。

任何想法?

/帕爾

回答

0

我是您使用FetchedResultsController與核心數據對象填寫表格假設。所以這個想法是你需要實現以下方法。

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

而且在commitEditingStyle:你只是刪除managedObjectContext的對象,並讓didChangeObject委託爲您處理表的修改。

didChangeObject

實現示例可以在這裏找到: Apple's document

+0

不幸的是,我沒有使用FetchedResultController。這是一個iPad應用程序,我不得不使用普通的UITableView。核心數據對象之前已經被獲取。 –

+0

那麼慣例是使用'FetchedResultsConttroller'來響應'UITableView'中的對象變化。從文檔:「NSFetchedResultsController的一個實例使用此協議中的方法來通知其委託,由於添加,刪除,移動或更新操作,控制器的提取結果已更改。」 – dombesz

+0

非常方便!但在這種情況下它並不能幫助我。 –

0

顯然你已經自己解決了這個問題,但是在你的代碼的問題是缺少在這裏你從數據源「刪除」對象的一部分。 在

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

你必須把:

if (editingStyle == UITableViewCellEditingStyleDelete) { 
    // delete obj from the context 
    [self.managedObjectContext deleteObject:[self coreDataObjectAtIndex:indexPath.row]; 
    // REMOVE obj from the dataSource (dataSource is your NSArray or NSMutableArray where are stored the objects 
    [dataSource removeObjectAtIndex:indexPath.row]; 
    // then refresh the tableView 
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
        withRowAnimation:UITableViewRowAnimationFade]; 
    } 
+0

感謝您的建議。不幸的是我不在我的數據源中使用NSMutableArray。我的模型類是定製的核心數據類,即在數據源委託方法numberOfRowsInSection中詢問表視圖中的行數,那時我需要核心數據堆棧刪除對象,否則我的模型將用錯誤的行數進行回答。換句話說,我需要用deleteRowsAtIndexPaths ::刷新表視圖,當我知道該對象已從管理對象上下文中刪除時。所以確切知道何時發生這一點至關重要。 –

+0

對不起,但是從你讀的行數? 如何建議@dombesz,或者你有nsfetchedresultcontroller,或者你有一個tableView dataSource方法可以知道它的錶行數的結構。 請問您可以發佈,例如'numberOfRowsInSection'方法代碼嗎? – strstr

+0

我讀了我的模型類的行數。我的模型類是自己的核心數據類(自定義)。所以我沒有用於表視圖的數據結構,也不使用NSFetchedResultController,因爲這對我來說不起作用。我在整個應用程序中使用模型類,並且在呈現表視圖之前通常會獲取對象。 numberOfRowsInSection的代碼很簡單: ' - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return actionList_.actions.count; }' –

相關問題