Core Data Asynchronous Fetching in Swift

In my previous post, I displayed a new Core Data feature that allows developers to perform batch updates directly on the Persistent Store. This time, I’m going to show how to perform asynchronous fetches, a feature that developers have desired for a long time, but has finally become available in iOS 8 (and OS X 10.10 Yosemite).

An asynchronous fetch allows developers to execute a fetch request without blocking the Managed Object Context for the duration of the fetch. As an extra feature, the asynchronous fetch is cancelable by the user and provides progress reporting through NSProgress.

When you perform a standard fetch request using the executeFetchRequest:error: method, the call does not return immediately. Instead, the thread is blocked until the fetch is completed (i.e. the fetched objects populate the Managed Object Context). An asynchronous fetch works differently. Developers perform an asynchronous fetch using the executeRequest:error: method (the same method used for batch updates). This method immediately returns an NSAsynchronousFetchResult. Once the fetch is completed, a completion block is executed.

Asynchronous fetches are only supported by Managed Object Contexts using either the NSPrivateQueueConcurrencyType or the NSMainQueueConcurrencyType (ConfinementConcurrencyType is not supported). Additionally, in order for the Managed Object Context to be updated at the end of the asynchronous fetch, you must specify it to do so.

Here’s how it works. First, create an NSFetchRequest as you would do in a standard fetch. You can use sort descriptors and predicates to be more selective on your data. Then, create an NSAsynchronousFetchRequest using the standard fetch request. After that, pass the asynchronous fetch request to the Managed Object Context executing the executeRequest:error: method on that context. The context immediately returns an NSAsynchronousFetchResult. At the same time, the context sends the fetch to the store. Now, you can continue editing that Managed Object Context performing fetches, faults, etc.

NSAsynchronousFetchRequest is a new subclass of NSPersistentStoreRequest. You can create an NSAsynchronousFetchRequest instance initializing it with an instance of a NSFetchRequest and a completion block.

NSAsynchronousFetchResult is a new subclass of NSPersistentStoreResult. It provides results or errors after the completion. It’s returned immediately by the Managed Object Context when you call executeRequest:error.

Fetching, fetching, fetching

Ok, now let’s see how to implement an asynchronous fetch request. Begin by creating a new project using the Single-View Application template. Name it AsynchronousFetch. Choose Swift as programming language and, of course, select Core Data.

For brevity, I am going to simplify some of the extra work you should do in a real app. First, I create fake data as I did in the post on the Batch Updates. So, select the Asynchronous_Fetch.xcdatamodeld file and add a new entity Person with two attributes:

  • name of type string
  • age of type int16

Generate the class file for the Person entity. To generate fake data let’s add this chunk of code inside the application:didFinishLaunchingWithOptions: of the AppDelegate class and run it just once.

After executing the app once, the persistent store is populated with 900 thousands records. Now, comment the above lines of code to avoid having to execute them again.

In the same method of the AppDelegate class, add the following lines of code:

This will pass the managed object context instance to the view controller.

For this example this is not relevant, but you should modify the line of code where you create the Managed Object Context. Search the managedObjectContext method in the AppDelegate class and modify the line:

with the following line:

Now, let’s move into the ViewController class. First, we need a property to hold the Managed Object Context created in the AppDelegate. So, add this property:

Next, let’s override the viewDidAppear: method, by adding the following method to the ViewController class:

After calling it on super, let’s create a fetch request for the entity Person:

After this, we can create an asynchronous fetch request:

As you can see, we are using the previously created fetch request to create the asynchronous fetch request object. The closure will be executed when the asynchronous fetch completes.

Since we want to report the progress of the fetch to the UI, let’s add a UIProgressView to the view of the view controller. Open the storyboard and add a progress view from the object library. Don’t forget to add autolayout. Create an outlet for the progress view:

Connect the progress view and the outlet. The progress view will show the progress of the fetch. To do so, we need to create an instance of NSProgress and make it observable.

Before creating the asynchFetch constant (see above), add the following lines of code:

Here, the first line creates an instance of NSProgress. The total unit count is 1, because the fetch is a stream operation and, since you don’t know how many objects you’re going to retrieve, you need to set its value to 1. The second line makes the view controller the observer of the progress instance. The fractionCompleted property is the observed property. The ProgressObserverContext represents the context used by the observer. You can define it before the ViewController class definition

After the asyncFetch constant, add the following lines of code:

Notice that line 1 (the performBlock: method) is not needed here, because we are using a single managed context. Here, I am adding this line, just to make sure that, if you are using two or more managed contexts in your app, you don’t forget to use it.

Finally, to make the fractionCompleted property KVO compliant, we need to implement the observeValueForKeyPath:ofObject:change:context: method:

Now, it’s ready to run.


Asynchronous fetching is a very powerful feature. Primarily because, it allows developers to continue to use the managed object context while the asynchronous fetch is executing. Together with the new batch updates functionality, asynchronous fetching adds interesting ways to work with managed object contexts and persistent stores.




(Visited 690 times, 1 visits today)