2
votes

I'm very used to creating a Core Data stack synchronously. However, I just noticed that this Apple provided example doesn't do that, instead it adds the persistent store coordinator on a background thread.

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/InitializingtheCoreDataStack.html

  1. Why?
  2. What are the ramifications?
  3. Will this approach 'just work' in place of a synchronous Core Data stack setup?
1
This is the kind of thing you want to do on a background thread. Avoiding the main thread in this case means setting this up won't block the UI. If your UI relies on the PSC, then you'll want to notify back on the main thread that it is ready. - Good Doug
@GoodDoug thanks, would this mostly apply to situations where the database is very large? From what I've seen, even moderately sized Core Data setups only hold up initial launch by a fraction of a second. - Jordan Smith
Its always a good idea to do stuff that is not directly UI related off the main thread. Just because it is quick right now, doesn't mean it will be quick when your app grows (or when something gets added to CoreData in the future) - Good Doug
@GoodDoug yep, that's true. I'm quite surprised at the number of apps, other Apple examples, and open source code I've seen that use a synchronous approach? Which makes me think that while you're correct, it's unlikely Apple would do anything crazy here. Although you never know. Feel free to add as an answer and I'll mark it correct - Jordan Smith
@Jordan The old Apple docs used to suggest doing that call synchronously. The docs were updated in 2015 to show the "correct" way. Therefore a lot of sample code used the out of date "incorrect" method. - Marcus S. Zarra

1 Answers

3
votes

The call to addPersistentStoreWithType... can block if you are doing a migration or interacting with iCloud. Therefore it is safer to throw that onto a background queue so that there is no risk of blocking the UI thread.

In addition, since the applicationDidFinishLaunching is on a ticking clock, you do not want to risk blocking that method for any longer than necessary. Since the example Core Data stack is created through that method, it is best to make sure it returns as quickly as possible.

Update

Any chance of adding how to handle this to your answer - i.e. how should the asynchronous addition be handled, any best practices? I'm guessing that fetched results controllers would update once the store coordinator is added, so showing some sort of 'loading' status in the UI until then may be best. It seems like a little too much for smaller projects though... would everything 'just work' without any code to handle the background setup? e.g. do fetches block until the coordinator is added?

In general your addPersistentStore call is going to finish long before any NSFetchedResultsController hits it. If the addPersistentStore does somehow come in after the NSFetchedResultsController fires then you will need to execute a second performFetch: as Core Data does not fire any internal notifications when that action is complete.

Personally, in the background queue, I will either execute a completionBlock/closure when the addPersistentStore is done or fire off a NSNotification. But I only add that after there is an issue that I have discovered during testing. Otherwise it is just pre-optimization.