2014-01-20 71 views
0

我仍然很難理解核心數據如何在後臺線程中工作,即使在閱讀了很多關於它的事情後,尤其是刪除對象。刪除核心數據對象並保存在後臺線程中

舉個例子,如果我想刪除這樣的背景下一個對象:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSManagedObjectContext *context = [self managedObjectContext]; 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     // Delete object from database 
     [context deleteObject:[self.tests objectAtIndex:indexPath.row]]; 
     NSError *error = nil; 
     if (![context save:&error]) { 
      NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]); 
      return; 
     } 
     [self.tests removeObjectAtIndex:indexPath.row]; 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

這個工作,但是當數據量大,[context save:&error]需要花費大量的時間,所以我該怎麼辦它在後臺? 看來我不能用另一個上下文工作,否則我得到錯誤an nsmanagedobjectcontext cannot delete objects in other contexts。 我已經嘗試了數百種不同的東西,但我迷失了... 謝謝!

回答

0

查看NSManagedObjectContext上的performBlock和performBlockAndWait方法。

我一直贊成使用NSPrivateQueueConcurrencyType,即使我的UI綁定託管對象上下文,因爲它避免了這種情況。例如,你可以做這樣的事情:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSManagedObjectContext *context = [self managedObjectContext]; 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    { 
     NSManagedObject *m = [self.tests objectAtIndex:indexPath.row]; 
     [context performBlock:^{ 
      [context deleteObject:m]; 

      if (![context save:&error]) { 
       //Note: You should really do something more useful than log this 
       NSLog(@"Can't Delete! %@ %@", error, [error localizedDescription]); 
      } 
     }]; 
     [self.tests removeObjectAtIndex:indexPath.row]; 
     [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
    } 
} 

的performBlock調用是異步的(而不是其同步對應performBlockAndWait),這將允許的tableView繼續更新的背景是在一個單獨的線程忙於拯救。

另外,您的託管對象上下文實例不應該經常更改。小型應用程序在其生命週期中僅分配一個NSManagedObjectContxt實例是很常見的。

+0

謝謝!這似乎工作。我只是想知道:是否可以只使用NSPrivateQueueConcurrencyType? – jcr

+0

只要您使用performBlock/perfomBlockAndWait從管理對象中讀取它就沒有問題。 Tableview代碼特別有點尷尬,因爲你必須從performBlockAndWait調用中複製這些值,將它們設置在單元格中。從NSMainQueueConcurrencyType開始(因此您可以在塊中設置單元格屬性),然後轉換爲專用隊列(如果有意義)。 – ImHuntingWabbits

1

您只能刪除objectcontext;在其中您獲取該託管對象。如果您正在使用seprate thread新的背景下,在這種情況下,你應該從managedObjectobjectId從第一個方面得到了這樣你就可以刪除對象

[context objectWithID:objectId]]; 

的NSManagedObjectID是上下文之間的相同,但NSManagedObject本身不是。

+1

(1)假設託管對象在持久存儲中 –

+0

任何crud操作都將在上下文中完成... –

1

作爲提到的其他答案,您只能從其上下文中刪除一個對象,並且上下文是線程綁定的。這裏的問題不是保存需要多長時間,而是您保存的位置。

您應該避免在任何面向像這樣的方法調用的UI中進行昂貴的操作。刪除後沒有理由立即保存。稍後保存,當用戶預期UI延遲時保存。核心數據將工作得很好,沒有保存。

相關問題