Using Core Data in the Background

Use Core Data in both a single-threaded and multithreaded app.


Core Data is designed to work in a multithreaded environment. However, not every object under the Core Data framework is thread safe. To use Core Data in a multithreaded environment, ensure that:

  • Managed object contexts are bound to the thread (queue) that they are associated with upon initialization.

  • Managed objects retrieved from a context are bound to the same queue that the context is bound to.

Comparing Main Queue and Private Queue Contexts

There are two types of managed object contexts: main queue and private queue. The type of context is defined as part of its initialization.

A main queue context (as defined by a NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType) is specifically for use with your application interface and can only be used on the main queue of your app.

A private queue context (as defined by a NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType) creates its own queue upon initialization and can be used only on that queue. Because the queue is private and internal to the NSManagedObjectContext instance, it can only be accessed through the perform(_:) and the performAndWait(_:) methods.

Initializing and Configuring Contexts

For both contexts, the initialization of the NSManagedObjectContext instance is the same:

let moc = NSManagedObjectContext(concurrencyType:<#type#>)

The parameter being passed in as part of the initialization determines what type of NSManagedObjectContext is returned.

When you use the NSPersistentContainer, you configure the viewContext property as a main queue (NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType) context, and configure the contexts associated with performBackgroundTask(_:) and newBackgroundContext() as a private queue (NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType).

Avoiding Problems

In general, avoid doing data processing on the main queue that is not user-related. Data processing can be CPU-intensive, and if it is performed on the main queue, it can result in unresponsiveness in the user interface. If your application will be processing data, like importing data into Core Data from JSON, create a private queue context and perform the import on the private context.

Do not pass NSManagedObject instances between queues. Doing so can result in corruption of the data and termination of the app. When it is necessary to hand off a managed object reference from one queue to another, use NSManagedObjectID instances.

You retrieve the managed object ID of a managed object by calling the objectID accessor on the NSManagedObject instance.

See Also

Background Tasks

Loading and Displaying a Large Data Feed

Consume data in the background, and lower memory usage by batching imports and preventing duplicate records in the Core Data store.

Conflict Resolution

Detect and resolve conflicts that occur when data is changed on multiple threads.

Batch Processing

Use batch processes to manage large data changes.