Latest 0.2.1
License MIT
Platforms ios 8.0, requires ARC

Adding concurrency/multi-threading to CoreData is not very straightforward and obvious. The main issue is with NSManagedObjectContext, which is thread unsafe. The default one created in AppDelegate is created on the main thread:

var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)

The main drawback of using AppDelegate‘s managed object context is that whenever a save, fetch or delete operation is performed, the main thread/UI will get blocked. If you are doing small operations, this may not be noticeable. But for larger operations, it will pose a problem.

The solution is to do such CoreData operations in the background and only when you have to do any UI changes, say reloading a table, you call reloadData on the main queue.


CocoaPods is the preferred way to install this library. Add this command to your Podfile:

pod 'ASJCoreDataOperation-Swift'


For the same library in Objective-C, see ASJCoreDataOperation.


  • Key: NSManagedObjectContext = moc

Concurrency options

There are three concurrency types defined in NSManagedObjectContext:

  • ConfinementConcurrencyType (which is marked deprecated from iOS 9.0)
  • PrivateQueueConcurrencyType
  • MainQueueConcurrencyType

You should not use ConfinementConcurrencyType anymore since it’s obsolete and Apple doesn’t recommend it. PrivateQueueConcurrencyType creates an moc on a background thread and MainQueueConcurrencyType creates one on the main queue. The one we are interested in is PrivateQueueConcurrencyType.

Creating an NSManagedObjectContext

You can create as many mocs as you wish. During saving, it must go through an NSPersistentStoreCoordinator to write data to an sqlite file. You can use the one implemented in AppDelegate or provide your own. Just make sure that no matter what kind of store your app has; NSSQLiteStoreType, NSBinaryStoreType or NSInMemoryStoreType, the coordinator object must be tied to the same destination.

var privateMoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMoc.persistentStoreCoordinator = appDelegatesPersistentStoreCoordinator;

There are two methods for mocs, performBlock(block: () -> Void) and performBlockAndWait(block: () -> Void). Any code written in those blocks is guaranteed to be executed on the same queue the moc is created. You must write your CoreData logic inside one of these methods. The difference between the two is that performBlockAndWait() will block the queue until it’s operation is completed.

Saving on a private queue

Whenever a save happens on a private moc, data will be written to the sqlite file but the main queue will not be notified about it. If you have an NSFetchedResultsController setup on the main queue, control will not reach its delegate methods. However, if the CoreData operation and NSFetchedResultsController share the same moc, it will work.

If you need the main queue to be notified about any changes made by a private context, you need to merge those changes from the private moc to the main moc. To do so, you have to start observing for NSManagedObjectContextDidSaveNotification on the private moc.

NSNotificationCenter.defaultCenter().addObserver(self, selector: "contextDidSave:", name: NSManagedObjectContextDidSaveNotification, object: privateMoc)

In contextDidSave: we need to merge the private moc changes into the main moc. You MUST use the moc‘s performBlock() or performBlockAndWait() methods to ensure the merge happens on the correct thread.

func contextDidSave(note: NSNotification)
  mainMoc.performBlock { () -> Void in

The note object has information of all modifications made to the managed objects. There can be issues however when merging data between two mocs and conflicts may arise. So, you must provide a mergePolicy so that CoreData knows how to resolve them.

privateMoc.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
  • Note: There is another concurrency pattern, using child and parent mocs which has a simpler setup but it is not recommended because it blocks the main queue.

What this library does

CoreDataOperation is a subclass of NSOperation that provides private queue support out of the box. This class is designed to be subclassed and will not work without it.

convenience init(privateMoc: NSManagedObjectContext!, mainMoc: NSManagedObjectContext!)

This is a convenience method to create an instance of your subclass. You may pass nil in both arguments or use the init() method. In those cases, a private moc will be created and AppDelegate‘s moc will be accessed to be used as the mainMoc. If your AppDelegate does not have an moc object, you must provide one that is created on the main queue.

public var privateMoc: NSManagedObjectContext!

Irrespective of the way the private moc is created, it is publicly exposed and you may use it, say to tie an NSFetchedResultsController to it and do asynchronous fetches.

public func coreDataOperation()

This is the method you are required to override in your subclass. Any CoreData operations you wish to perform should be written here. The library will ensure that this method is called on the correct thread.


var operationQueue = NSOperationQueue()
let operation = SomeCoreDataOperationSubclass(privateMoc: self.photosPrivateMoc, mainMoc: nil)

As soon the operation is added to the operationQueue, it will start running on a background queue.



  • A completion block to know when operation is complete
  • A way to cancel operation midway


ASJCoreDataOperation-Swift is available under the MIT license. See the LICENSE file for more info.

Latest podspec

    "name": "ASJCoreDataOperation-Swift",
    "version": "0.2.1",
    "platforms": {
        "ios": "8.0"
    "license": {
        "type": "MIT"
    "homepage": "",
    "authors": {
        "Sudeep Jaiswal": "[email protected]"
    "summary": "Do asynchronous CoreData operations without blocking your UI",
    "source": {
        "git": "",
        "tag": "0.2.1"
    "source_files": "ASJCoreDataOperation-Swift/*.swift",
    "requires_arc": true

Pin It on Pinterest

Share This