2012-07-25 21 views

回答

4

您可以在多線程方式使用核心數據,但你應遵循approaches recommended by Apple之一:

The pattern recommended for concurrent programming with Core Data is thread confinement: each thread must have its own entirely private managed object context.

There are two possible ways to adopt the pattern:

Create a separate managed object context for each thread and share a single persistent store coordinator. This is the typically-recommended approach.

Create a separate managed object context and persistent store coordinator for each thread. This approach provides for greater concurrency at the expense of greater complexity (particularly if you need to communicate changes between different contexts) and increased memory usage.

特別:

Using thread confinement, you should not pass managed objects or managed object contexts between threads. To 「pass」 a managed object from one context another across thread boundaries, you either:

Pass its object ID (objectID) and use objectWithID: or existingObjectWithID:error: on the receiving managed object context. The corresponding managed objects must have been saved—you cannot pass the ID of a newly-inserted managed object to another context.

Execute a fetch on the receiving context. These create a local version of the managed object in the receiving context.

從這一點隨之而來,你不能創建管理對象在一個線程中(有自己的上下文),然後將它們保存在另一個線程中。

因此,爲了實現您的願望,您需要在線程之間共享託管對象上下文或持久存儲協調器。在這種情況下,你應該正確使用鎖定技術來防止您的商店進入不一致的狀態:

If you share a managed object context or a persistent store coordinator between threads, you must ensure that any method invocations are made from a thread-safe scope. For locking, you should use the NSLocking methods on managed object context and persistent store coordinator instead of implementing your own mutexes. These methods help provide contextual information to the framework about the application's intent—that is, in addition to providing a mutex, they help scope clusters of operations.

我不建議走這條路,如果您有任何機會修改您的應用程序的設計,使您不需要進入核心數據對象的鎖定和同步。

1

你所要求的大小合適嵌套上下文。您創建一個私有隊列上下文,並將其直接附加到persistent-store-coordinator。很簡單。以你目前的代碼,而不是這個......

managedObjectContext = [[NSManagedObjectContext alloc] init]; 

這種替換...

workerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

現在,你已經取代了傳統的坐月子MOC一個新的MOC將運行擁有自己的併發隊列。

獲得您可以從主線程中使用你的背景,你創建另一個管理對象上下文,並使其剛纔創建的一個的孩子......

managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
managedObjectContext.parent = workerManagedObjectContext; 

這意味着你可以像以前一樣使用managedObjectContext。但是,現在它不是直接進入商店,而是經過中間環境。父上下文將在其自己的後臺線程中執行工作。

因此,您可以對所需的managedObjectContext進行所有更改。當談到時間來保存,你做這樣的事......

static void saveManagedObjectContext(NSManagedObjectContext *moc, void(^completionBlock)(NSError *error)) { 
    [moc performBlock:^{ 
     NSError *error = nil; 
     if (moc.hasChanges && [moc save:&error] && moc.parentContext) { 
      saveManagedObjectContext(moc.parentContext, completionBlock); 
     } else { 
      completionBlock(error); 
     } 
    }]; 
} 

編輯

如果要普遍使用,您可以輕鬆地將它添加到一個類別上的NSManagedObjectContext,然後只是打電話...

[managedObjectContext saveWithCompletionBlock:^(NSError *error){ 
    if (error) { 
     // Handle the error 
     return; 
    } 
    // Handle success... 
}]; 
0

Apple建議爲單獨的線程使用單獨的上下文。一旦你調用了保存,它就會被保存到實際數據庫中的上下文狀態。如果您需要將主線程更改反映到後臺線程中,請將後臺線程上下文與主線程上下文合併並調用保存。

相關問題