1

I'm rewriting a big piece of code in an app that combines coredata with server requests. And I'm trying to figure out the best way to go about it so that I can update objects concurrently as soon as new server requests return with new JSON. BTW, if iOS7 makes the solution any better, feel free to assume the code will only need to be iOS7-compatible.

Here's a basic use case:

Say I have a User entity with a id and name attributes and 2 M2M (User/User) relationships: friends. and eh... fiends? Sure.

So the app starts. Nothing is in the in-memory graph nor the SQL persistent store. I ask to retrieve user with id 15 along with its friends and fiends.

What happens next is:

  1. CD does a fetch on User with a predicate of type id = 15.
  2. Nothing comes back, so it enqueues 3 AFRequests for the following server endpoints: A: /users/15 (this will get the user attributes, id and name), B: users/15/friends (relationship) and C: users/15/fiends (relationship). These 3 requests are concurrent.
  3. The minute that any of these requests returns (with the JSON representation of the user or an array of friends/fiends for the relationships), I query the CD context to see if any object in the JSON payload already exists in CD. If it does (which would happen in subsequent server calls), I update them with any new data from the server (including establishing relationships if applicable). If not, I create a new managed object in the CD context and populate attributes / relationships from the JSON. The creation and identification of an object in this case is always based on its id attribute.
  4. Either way, when I'm done I save the CD context.

From the above, every time JSON comes back from the server I create or update the corresponding managed objects and save. The problem is, for this example, that the same context will get 3 potentially concurrent calls: create user 15 and/or populate its friends, create user 15 and/or populate its fiends, create user 15 and/or update its name and id.

My original plan was:

  1. make the 3 AFRequests one after the other (which I'd assume go into a concurrent queue and so will execute concurrently)
  2. Have the completion blocks of the requests all be dispatched in the same GCD concurrent queue.
  3. have each GCD block create a new CD context, do insertions/updates and then call save
  4. have the main CD context merge the changes in the main thread.

But now I just read a bit about the two queue concurrency types for a NSManagedObjectContext as well as -performBlock: and the concept of child contexts, and I don't fully get it yet. So I was wondering, does my original plan sound viable?

A few questions I can think of are:

  • Is it better instead, for step 3, to create a child context of the main context, with NSPrivateQueueConcurrencyType, for each GCD block?
  • If so do I even still need the GCD queue? That is, should I instead use a single context with NSPrivateQueueConcurrencyType and instead of dispatching via GCD, just do -performBlock:?
SaldaVonSchwartz
  • 3,769
  • 2
  • 41
  • 78
  • similar situation as yours. i use NSURLConnection asynchronously fetch the data from JSON. and write the date to Core Data (create new NSManagedObject or update existed one). I avoid to use concurrency as it's complicated in both server fetch and core data context management. And its benefit is limited when the data fetch is not that heavy – Jing Oct 24 '13 at 03:46

0 Answers0