jrhee17
jrhee17

Reputation: 1152

IOS Core Data asynchronous saving

Problem Statement

I am having trouble saving server side data asynchronously.

Structure

I am using the following structure of NSManagedObjectContext in order of parent to child:

  1. writerManagedObjectContext (NSPrivateQueueConcurrencyType)
  2. masterManagedObjectContext (NSMainQueueConcurrencyType)
  3. backgroundManagedObjectContext (NSPrivateQueueConcurrencyType)

Code

I am using the following code to save data

[backgroundManagedObjectContext performBlock:^{
    [backgroundManagedObjectContext save:nil];
    [masterManagedObjectContext performBlock:^{ // Starts blocking UI from here
        [masterManagedObjectContext save:nil];
        [writerManagedObjectContext performBlock:^{
            [writerManagedObjectContext save:nil];
        }]
    }]
}]

Problem

The code saves fine. The backgroundManagedObjectContext also saves asynchronously. However, both masterManagedObjectContext and writerManagedObjectContext refuse to be saved asynchronously and blocks the UI thread. (I know it blocks the UI thread because I tried to perform actions which have nothing to do with Core Data and they were also blocked. This is not a case of the persistent coordinator not being accessible)

Questions

  1. What would be the reason the above code blocks the main thread?
  2. Am I correct in assuming I can call the above code from anywhere since the save will be called in each respective thread/context?

Any help would be much appreciated.

Edit

http://floriankugler.com/2013/04/29/concurrent-core-data-stack-performance-shootout/

Apparently the freeze comes from the attempt to propagate to the parent NSManagedObjectContext. The article seems to elude to the fact that it is impossible to have a truly asynchronous save to the main context.

The data was heavily linked, 5MB, and took approximately 40s to save to psc. I don't think I'll use a parallel structure as described in the post since the code base is already large as it is. I would appreciate any strategies I can utilize to decrease this freeze.

Upvotes: 1

Views: 1437

Answers (1)

jp2g
jp2g

Reputation: 692

Even though backgroundManagedObjectContext is a private queue context it still propagates its changes up to masterManagedObjectContext, being its parent. This could be where it's choking up. Merging changes from child contexts still takes up CPU time, the effects of which become more pronounced in a busy queue like the UI's.

You can always use Instruments to analyze what's going on.

If your particular use case permits, try setting backgroundManagedObjectContext.persistentStoreCoordinator to the same psc as writerManagedObjectContext and not make it a child of masterManagedObjectContext.

Better yet, use an awesome framework like MagicalRecord. Doesn't shield you from problems like this, but less code makes things (arguably) a bit easier to debug.

Upvotes: 1

Related Questions