我一直在阅读有关在NSManagedObjectContext
中使用父级和子级Core Data
的一些链接和帖子,但我发现的示例方案只涉及编辑特定属性父上下文中的对象,然后将更改推送到父上下文。
我需要处理的场景有点复杂,我不确定如何管理它:
我在默认上下文中有一组托管对象(主队列中AppDelegate
中提供的对象)。我的应用程序定期调用Web服务以检查是否有这些对象的更新。我想在一个单独的线程中执行这些更新,以避免阻止de UI,因此,当它需要调用de服务来请求更新时,我这样做:
let bundle = NSBundle.mainBundle()
let modelURL = bundle.URLForResource("MyApp", withExtension: "momd")
let model = NSManagedObjectModel(contentsOfURL: modelURL!)!
let psc = NSPersistentStoreCoordinator(managedObjectModel: model)
let privateContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
privateContext.persistentStoreCoordinator = psc
let documentsURL = CoreDataHelper.applicationDocumentsDirectory()
let storeURL = documentsURL.URLByAppendingPathComponent("MyApp.sqlite")
let options = [NSMigratePersistentStoresAutomaticallyOption: true]
var error: NSError? = nil
let store: NSPersistentStore? = psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: options, error: &error)
也就是说,我在私有队列中创建一个新的上下文,并使用自己的新持久性存储协调器和持久存储。
一旦我拥有私人环境,我就会要求更新服务:
[privateContext performBlockAndWait: ^{
// Call services
// Create new objects in this private context with
// the data in services responses
}];
此时一切都还不错。我有一个" old"在我的主要上下文中的一组对象,以及一个" new"私有上下文中的对象集。我需要用私有对象中的新对象替换主上下文的对象集。这里的问题是:
我不知道父/子上下文是否可以处理这种更新,或者它们只适合让用户编辑某些对象。这里不是编辑对象的用户,因此我需要避免阻止UI,而且我不仅要修改对象信息,还要删除和添加新对象(如果需要)。
我对父/子情境有一些疑问:
我需要帮助才能了解其工作原理以及管理我的方案的最佳方式。
提前致谢。
列出项目
答案 0 :(得分:0)
以下是一些代码段:
// Set the moc here because its defined as Lazy it may be initialised to nil already by
// something!
let newMoc = NSManagedObjectContext()
newMoc.persistentStoreCoordinator = persistentStoreCoordinator
// Set the MergePolicy to prioritise external inputs
let mergePolicy = NSMergePolicy(mergeType:NSMergePolicyType.MergeByPropertyStoreTrumpMergePolicyType )
newMoc.mergePolicy = mergePolicy
managedObjectContext = newMoc
...
/* Loads the required seed data */
// Usually called on a background thread and therefor we need to process the DidSave notification
// to merge the changed with the main context so the UI gets updated
func loadSeedData() {
//FLOG(" called");
let bgContext:NSManagedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.ConfinementConcurrencyType)
// Register for saves in order to merge any data from background threads
NSNotificationCenter.defaultCenter().addObserver(self, selector:"storesDidSave:", name: NSManagedObjectContextDidSaveNotification, object:bgContext)
while (persistentStoreCoordinator == nil) {
//FLOG(@" persistentStoreCoordinator = nil, waiting 5 seconds to try again...");
sleep(5);
}
bgContext.persistentStoreCoordinator = persistentStoreCoordinator
insertNewWalletDetails(bgContext, name:"Info")
...
bgContext.processPendingChanges()
do {
try bgContext.save()
//FLOG(" Seed data loaded")
} catch {
//FLOG(" Unresolved error \(error), \(error?.userInfo)")
}
...
// We only care if the one we have open is changing
func registerForStoreChanges(storeCoordinator: NSPersistentStoreCoordinator) {
//FLOG("registerForStoreChanges called")
let nc = NSNotificationCenter.defaultCenter()
nc.addObserver(self, selector: "storesWillChange:", name: NSPersistentStoreCoordinatorStoresWillChangeNotification, object: storeCoordinator)
nc.addObserver(self, selector: "storesDidChange:", name: NSPersistentStoreCoordinatorStoresDidChangeNotification, object: storeCoordinator)
nc.addObserver(self, selector: "storesDidImport:", name: NSPersistentStoreDidImportUbiquitousContentChangesNotification, object: storeCoordinator)
}
...
// NB - this may be called from a background thread so make sure we run on the main thread !!
// This is when transaction logs are loaded
func storesDidSave(notification: NSNotification!) {
// Ignore any notifications from the main thread because we only need to merge data
// loaded from other threads.
if (NSThread.isMainThread()) {
//FLOG(" main thread saved context")
return
}
NSOperationQueue.mainQueue().addOperationWithBlock {
//FLOG("storesDidSave ")
// Set this so that after the timer goes off we perform a save
// - without this the deletes don't appear to trigger the fetchedResultsController delegate methods !
self.import_or_save = true
self.createTimer()
if let moc = self.managedObjectContext {
moc.mergeChangesFromContextDidSaveNotification(notification)
}
}
}
对于工作示例应用和其他说明,请查看enter link description here