Core Data Stack #2 – 1 context, background task

  • http://www.cocoabuilder.com/archive/cocoa/290810-core-data-conflict-detection.html
  • http://joelparsons.net/blog/2013/09/02/background-core-data-with-privatequeuecontext

Updated Demo 5/5/2016

demo 10/26/2015

Have the context process in the background

First step is to add a private queue context where it will save a lot of data into the database.

  1. add a NSManagedObjectContext privateQueueContext object, synthesize it
  2. custom set method where we create the context with a queue
  3. queue up tasks such as bulk add
full source for CoreDataStack.h

addBulkPeople method is the process of using our privateQueueContext object and throwing a block on the queue and processing the saving of data into the database.

reportOnAllPeopleToLog method is using our mainQueueContext to simply get data from CoreData and see what’s in the database.

CoreDataStack.m

First, we set up our init method and init our queue contexts via custom setter methods.

Notice when we alloc and init NSManagedObjectContext, we initialize the context with concurrency type NSPrivateQueueConcurrencyType

Essentially, instead of the old way of attaching a context to a thread, we now have the option of attaching a context to a queue. This means that whatever job and/or tasks are lined up for this context gets queued. Thus, whatever operation needs to be done by that context will be completed FIFO via blocks.

Now that we have our queue context ready to be used, use queue up tasks by adding in blocks of code to the queue. We want to add a bulk of people so we queue up the task of “adding 10,000 people”. This is obviously a very time consuming task, and by adding it onto our context queue, we make it run in the background. Thus, freeing up the main thread for UI operations.

reportOnAllPeopleToLog

…simply reads the Core Data and displays the results.

Keep in mind that in the demo, the mainQueueContext is initialized with
NSMainQueueConcurrencyType, which runs on the main thread.

Thus, you SHOULD put tasks that update UI here.

If you are to use a time consuming task like a loop that displays all the People (like how we’re doing it), expect the main UI to freeze.

If you want to change it so that logging is done in the background and not freeze the UI, then change the NSMainQueueConcurrencyType to NSPrivateQueueConcurrencyType.

Then, put your code inside [self.mainQueueContext performBlock:^{…}.

Below are just some of the standard methods for the core stack.

Now, run the app. Make sure there is no previous version installed because we want a clean database.

Click on the add bulk button so we let it add 10,000 people into the database. Then play around with the scrollbar, you’ll notice that its responsive. Hence, we’ve successfully used the context to queue up jobs and run them on a background queue. The main thread is then responsive.

add_bulk

If you want to display all the Persons you’ve added, click on the display all button. The display all button uses the mainQueueContext, which runs on the main UI. Hence, put all the code that updates the UI, into that queue.

display_all

For demonstration purposes, we are using NSPrivateQueueConcurrencyType for the mainQueueContext. Hence, anything you do on on that context SHOULD BE TO UPDATE THE UI.

If you do labor intensive job such as logging all the People you’ve added, the UI will freeze…as demonstrated in the updated demo project.

IF you want to do the logging in the background, you can change it to NSPrivateQueueConcurrencyType:

then place your logging task in the performBlock like so:

Then, your logging will be executed in the background and not block the UI.

Next, using multiple contexts >>