I'm doing some background processing in an app with core data. The background processing is done on a child managedObjectContext. Context initialization:
appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
// the moc in appDelegate is created with .MainQueueConcurrencyType
mainThreadMOC = appDelegate.managedObjectContext!
backgroundMOC = NSManagedObjectContext(concurrencyType:NSManagedObjectContextConcurrencyType.PrivateQueueConcurrencyType)
backgroundMOC?.parentContext = mainThreadMOC
Background processing is done in the following method:
// download all new transaction log entries
func syncItems() {
... set up the query object for parse
let moc = CoreDataStore.sharedInstance.backgroundMOC
// perform download
moc?.performBlock( {
self.runQuery(query) // Download stuff und do some core data work
})
}
The debugger shows that all work inside the block is indeed in a background thread.
When I call this function from the main thread and immediately block the main thread (for test purpose) with a lengthy core data operation, I see that the background thread stops and only continues execution when the main thread is idle.
// this is called from a view controller in the main thread
syncItems() // should start to work in background
for i in 0...200 {
// do some core data work in main thread
}
// syncItems starts to work after the blocking for-loop ends.
Why is that happening?
Don’t use a parent-child context setup.
Parent-child context are not a good approach for just about anything. Just use a simple stack: two contexts with one shared persistent store coordinator.
Parent-child contexts just add a lot of confusion without giving you much of anything. It’s a pretty misunderstood concept. I wish people like mzarra would f***ing stop advocating that setup. It’s a disservice to the community.
If your background context is a child context of your main context, you will have to lock both the main and the background context, whenever the background context needs to save. This blocks the UI. And you’ll have to lock the UI a 2nd time to propagate those changes from the UI into the PSC. If you use a background context, you will have to merge changes into the main context, but you'll only do work for those objects that are currently registered with that context. If you added new objects, or updated / deleted objects that are not currently registered (referenced) that’s basically a no-op.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With