我想更改主線程上的核心數據對象,然後保存在後臺線程中。後臺線程保存會包含主線程更改嗎?核心數據是否保存來自其他線程的更改?
回答
您可以在多線程方式使用核心數據,但你應遵循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.
我不建議走這條路,如果您有任何機會修改您的應用程序的設計,使您不需要進入核心數據對象的鎖定和同步。
你所要求的大小合適嵌套上下文。您創建一個私有隊列上下文,並將其直接附加到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...
}];
Apple建議爲單獨的線程使用單獨的上下文。一旦你調用了保存,它就會被保存到實際數據庫中的上下文狀態。如果您需要將主線程更改反映到後臺線程中,請將後臺線程上下文與主線程上下文合併並調用保存。
- 1. 在線程中保存核心數據
- 2. 核心數據:setPrimitiveValue並保存更改
- 3. 核心數據保存更改撤銷
- 4. 如何保存核心數據中的單個屬性更改而未保存其他更改?
- 5. NSArrayController的+ NSTableView的:自動保存更改而不核心數據
- 6. Iphone核心數據 - 是否自動保存?
- 7. 核心數據 - 是否有可能避免在主線程中保存managedObjectContext?
- 8. 來自遠程數據源的核心數據存儲
- 9. 保存NSNumber核心數據
- 10. 核心數據保存
- 11. 保存核心數據?
- 12. 保存在覈心數據
- 13. 核心數據:未保存
- 14. 保存來自For循環的核心數據屬性 - iOS
- 15. 保存來自多個TableVIews的核心數據
- 16. 關係線程中的核心數據保存對象
- 17. 核心數據未保存對Transformable屬性的更改
- 18. 使用核心數據保存對現有實體的更改
- 19. 在NSManagedObjectContext中保存更改的核心數據問題
- 20. 核心數據提取請求和未保存的更改
- 21. 多線程核心數據
- 22. 核心數據NSManagedObject更改
- 23. 核心數據和多線程崩潰保存
- 24. 保存由textFieldDidEndEditing更改的textfield值不會保存在覈心數據中嗎?
- 25. 核心數據保存VS合併更改
- 26. iOS核心數據udpate:更改沒有保存
- 27. 離線數據存儲/同步選項,核心數據,TouchDB或其他?
- 28. 核心數據和多線程(和綁定,使其更有趣)
- 29. 將核心位置數據保存到核心數據?
- 30. 將核心數據保存到核心數據
3號很棒!非常感謝。 – Armin 2013-06-16 19:28:37