SlideShare a Scribd company logo
1 of 54
Download to read offline
Core Data
with multiple managed
   object contexts



                        Photo by Free-Photo-Gallery.org
Core Data
with multiple managed
   object contexts



                        Photo by Free-Photo-Gallery.org
Matt(hew) Morey
                   Senior Developer at ChaiONE
                                        Traveler
                             Boardsport Junkie




      matthewmorey.com | @xzolian
Agenda


1)Core Data Basics
2)Concurrency Problems
3)Concurrency Solutions
Agenda


1)Core Data Basics
2)Concurrency Problems
3)Concurrency Solutions
Basics
Basics

                          App

                    NSManagedObject

                NSManagedObjectContext

NSPersistentStoreCoordinator      NSManagedObjectModel

                    NSPersistentStore

  SQLite      XML        Binary      In Memory   Custom
Basics

                          App

                    NSManagedObject

                NSManagedObjectContext

NSPersistentStoreCoordinator      NSManagedObjectModel

                    NSPersistentStore

  SQLite      XML        Binary      In Memory   Custom
Managed Object Model
Managed Object Model
Managed Object Model
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"core-data"
                                                 withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc]
                                        initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}
Persistent Store Coordinator
Persistent STore Coordinator
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"core-data.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self
                                                                                                    managedObjectModel]];

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                   configuration:nil
                                                             URL:storeURL
                                                         options:nil
                                                           error:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.
         ...
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}
Persistent STore Coordinator
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"core-data.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self
                                                                                                    managedObjectModel]];

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                   configuration:nil
                                                             URL:storeURL
                                                         options:nil
                                                           error:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.
         ...
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}
Managed Object Context
Managed Object Context
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}
Single Context
Single Context
Single Context


                Code Example
https://github.com/mmorey/CoreDataMultiContext/tree/blocking
Agenda


1)Core Data Basics
2)Concurrency Problems
3)Concurrency Solutions
Problems

‣Core Data Managed Objects are not thread safe
 ‣Must pass Object IDs to use across threads

‣Objects are locked for all operations including read
 ‣Objects that feed the UI must be fetched on the main thread
Agenda


1)Core Data Basics
2)Concurrency Problems
3)Concurrency Solutions
Traditional Multi-Context

Pre-iOS 5: Thread Confinement
‣Single NSMangedObjectContext per thread
‣Manual notifications, merging, and saving
‣Fairly easy to understand, but harder to manage
Traditional Multi-Context
Traditional Multi-Context
- (void)loadData{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

          // Create temp context
          NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
          [context setPersistentStoreCoordinator:[(AppDelegate *)[[UIApplication sharedApplication] delegate]
                                                                                     persistentStoreCoordinator]];
          //
          // Do lots of async work here
          //

          // Save the context.
          error = nil;
          if (![context save:&error]) {
              // Replace this implementation with code to handle the error appropriately.
              abort();
          }

    });
}

// Register for save notification in ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(contextDidSave:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:context];
Traditional Multi-Context
- (void)loadData{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

          // Create temp context
          NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
          [context setPersistentStoreCoordinator:[(AppDelegate *)[[UIApplication sharedApplication] delegate]
                                                                                     persistentStoreCoordinator]];
          //
          // Do lots of async work here
          //

          // Save the context.
          error = nil;
          if (![context save:&error]) {
              // Replace this implementation with code to handle the error appropriately.
              abort();
          }

    });
}

// Register for save notification in ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(contextDidSave:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:context];
Traditional Multi-Context
- (void)loadData{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

          // Create temp context
          NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
          [context setPersistentStoreCoordinator:[(AppDelegate *)[[UIApplication sharedApplication] delegate]
                                                                                     persistentStoreCoordinator]];
          //
          // Do lots of async work here
          //

          // Save the context.
          error = nil;
          if (![context save:&error]) {
              // Replace this implementation with code to handle the error appropriately.
              abort();
          }

    });
}

// Register for save notification in ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(contextDidSave:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:context];
Traditional Multi-Context
- (void)contextDidSave:(NSNotification *)notification {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSManagedObjectContext *mainContext = [self.fetchedResultsController
                                                          managedObjectContext];

          [mainContext mergeChangesFromContextDidSaveNotification:notification];
    });
}

// Or

- (void)contextDidSave:(NSNotification *)notification {
    [self.managedObjectContext performSelectorOnMainThread:
                          @selector(mergeChangesFromContextDidSaveNotification:)
                                                withObject:notification
                                             waitUntilDone:NO];
}
Traditional Multi-Context
- (void)contextDidSave:(NSNotification *)notification {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSManagedObjectContext *mainContext = [self.fetchedResultsController
                                                          managedObjectContext];

          [mainContext mergeChangesFromContextDidSaveNotification:notification];
    });
}

// Or

- (void)contextDidSave:(NSNotification *)notification {
    [self.managedObjectContext performSelectorOnMainThread:
                          @selector(mergeChangesFromContextDidSaveNotification:)
                                                withObject:notification
                                             waitUntilDone:NO];
}
Traditional Multi-Context


                      Code Example
https://github.com/mmorey/CoreDataMultiContext/tree/notification-context
Parent Child Context

≥ iOS 5: Parent Child Contexts
‣Grand Central Dispatch private dispatch queues
‣Threading managed for you, no manual synchronization required
‣Less complicated and more flexible than pre-iOS 5 method
‣Context can and should be nested
Concurrency Types
NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc]
                                        initWithConcurrencyType:NSPrivateQueueConcurrencyType];

                ‣NSConfinementConcurrencyType
                 ‣Separate contexts for each thread
                 ‣Default, Legacy option
                ‣NSPrivateQueueConcurrencyType
                 ‣MOC maintains private serialized queue
                 ‣Can be created from any other thread
                 ‣Idle queues are more efficient than extra threads
                ‣NSMainQueueConcurrencyType
                 ‣Similar to private queue but on the main queue
Parent Child Context
Parent Child Context



  PSC                  PSC
Parent Child Context
__block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication]
                                                                         delegate] managedObjectContext];
NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc]
                                                  initWithConcurrencyType:NSPrivateQueueConcurrencyType];
temporaryContext.parentContext = managedObjectContext;

[temporaryContext performBlock:^{

    //
    // Do lots of async work here
    //

    // Save the context.
    NSError *error = nil;
    if (![temporaryContext save:&error]) {abort();}

    [managedObjectContext performBlock:^{
        // Save the context.
        NSError *error = nil;
        if (![managedObjectContext save:&error]) {abort();}

    }]; // main
}]; // temp context
Parent Child Context
__block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication]
                                                                         delegate] managedObjectContext];
NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc]
                                                  initWithConcurrencyType:NSPrivateQueueConcurrencyType];
temporaryContext.parentContext = managedObjectContext;

[temporaryContext performBlock:^{

    //
    // Do lots of async work here
    //

    // Save the context.
    NSError *error = nil;
    if (![temporaryContext save:&error]) {abort();}

    [managedObjectContext performBlock:^{
        // Save the context.
        NSError *error = nil;
        if (![managedObjectContext save:&error]) {abort();}

    }]; // main
}]; // temp context
Parent Child Context
__block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication]
                                                                         delegate] managedObjectContext];
NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc]
                                                  initWithConcurrencyType:NSPrivateQueueConcurrencyType];
temporaryContext.parentContext = managedObjectContext;

[temporaryContext performBlock:^{
                                                                Private Queue save
    //
    // Do lots of async work here
    //
                                                              propagates up to parent
    // Save the context.
    NSError *error = nil;
    if (![temporaryContext save:&error]) {abort();}

    [managedObjectContext performBlock:^{
        // Save the context.
        NSError *error = nil;
        if (![managedObjectContext save:&error]) {abort();}

    }]; // main
}]; // temp context
Parent Child Context
__block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication]
                                                                         delegate] managedObjectContext];
NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc]
                                                  initWithConcurrencyType:NSPrivateQueueConcurrencyType];
temporaryContext.parentContext = managedObjectContext;

[temporaryContext performBlock:^{                              Save to disc still locks PS
    //                                                        which will block the UI during
    // Do lots of async work here
    //                                                              read operations
    // Save the context.
    NSError *error = nil;
    if (![temporaryContext save:&error]) {abort();}

    [managedObjectContext performBlock:^{
        // Save the context.
        NSError *error = nil;
        if (![managedObjectContext save:&error]) {abort();}

    }]; // main
}]; // temp context
Basics

                          App

                    NSManagedObject

                NSManagedObjectContext

NSPersistentStoreCoordinator      NSManagedObjectModel

                    NSPersistentStore

  SQLite      XML        Binary      In Memory   Custom
Async Saving - Parent Child Context
Async Saving - Parent Child Context
// Child context
- (NSManagedObjectContext *)managedObjectContext{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _managedObjectContext.parentContext = [self writerManagedObjectContext];

    return _managedObjectContext;
}

// Parent context
- (NSManagedObjectContext *)writerManagedObjectContext{
    if (_writerManagedObjectContext != nil) {
        return _writerManagedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:
                                                                                 NSPrivateQueueConcurrencyType];
        [_writerManagedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _writerManagedObjectContext;
}
Async Saving - Parent Child Context
// Child context
- (NSManagedObjectContext *)managedObjectContext{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _managedObjectContext.parentContext = [self writerManagedObjectContext];

    return _managedObjectContext;
}

// Parent context
- (NSManagedObjectContext *)writerManagedObjectContext{
    if (_writerManagedObjectContext != nil) {
        return _writerManagedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:
                                                                                 NSPrivateQueueConcurrencyType];
        [_writerManagedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _writerManagedObjectContext;
}
Async Saving - Parent Child Context
// Child context
- (NSManagedObjectContext *)managedObjectContext{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    _managedObjectContext.parentContext = [self writerManagedObjectContext];

    return _managedObjectContext;
}

// Parent context
- (NSManagedObjectContext *)writerManagedObjectContext{
    if (_writerManagedObjectContext != nil) {
        return _writerManagedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:
                                                                                 NSPrivateQueueConcurrencyType];
        [_writerManagedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _writerManagedObjectContext;
}
Parent Child Context
__block NSManagedObjectContext *writerObjectContext = [(AppDelegate *)[[UIApplication sharedApplication]
                                                                   delegate] writerManagedObjectContext];
__block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication]
                                                                         delegate] managedObjectContext];
__block NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc]

initWithConcurrencyType:NSPrivateQueueConcurrencyType];
temporaryContext.parentContext = managedObjectContext;

[temporaryContext performBlock:^{
    //
    // Do lots of async work here
    //
    [temporaryContext save:&error]; {abort();} // Save the context.

    [managedObjectContext performBlock:^{
        [managedObjectContext save:&error]; {abort();} // Save the context.

        [writerObjectContext performBlock:^{
            [writerObjectContext save:&error]; {abort();} // Save the context.
        }]; // writer
    }]; // main
}]; // temp context
Parent Child Context
__block NSManagedObjectContext *writerObjectContext = [(AppDelegate *)[[UIApplication sharedApplication]
                                                                   delegate] writerManagedObjectContext];
__block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication]
                                                                         delegate] managedObjectContext];
__block NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc]

initWithConcurrencyType:NSPrivateQueueConcurrencyType];
temporaryContext.parentContext = managedObjectContext;

[temporaryContext performBlock:^{                                         NSPrivateQueueConcurrencyType
    //
    // Do lots of async work here
    //                                                                  NSMainQueueConcurrency
    [temporaryContext save:&error]; {abort();} // Save the context.

    [managedObjectContext performBlock:^{
        [managedObjectContext save:&error]; {abort();} // Save the context.

        [writerObjectContext performBlock:^{
            [writerObjectContext save:&error]; {abort();} // Save the context.
        }]; // writer
    }]; // main
}]; // temp context
Asynchronous Saving - Parent Child Context


                         Code Example
      https://github.com/mmorey/CoreDataMultiContext/tree/parent-context
Still Blocking?
Still Blocking?


Small and frequent saves during import
Still Blocking?


Wait for opportunity when user won’t notice
Still Blocking?


- (void)setStalenessInterval:(NSTimeInterval)expiration
Still Blocking?


           NSFetchedResultsController *aFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"sections"
                         cacheName:@"default-cache"];
Still Blocking?

 For VERY LARGE amounts of data it may be
  better to generate the SQLite file on the
server, download it asynchronously, and set it
     up as an additional persistent store.
References
                                       Nested MOC Release Notes:
      http://developer.apple.com/library/mac/#releasenotes/DataManagement/RN-CoreData/index.html

                                      Core Data Programming Guide:
http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.html

                                          Cocoanetics Blog:
                      http://www.cocoanetics.com/2012/07/multi-context-coredata/
                         http://www.cocoanetics.com/2013/02/zarra-on-locking/
Thanks!
              Questions? Get in Touch.
                        Twitter: @xzolian
                        App.net: @morey
          Email: matt@matthewmorey.com
           URL: http://matthewmorey.com

More Related Content

Similar to Core Data with multiple managed object contexts

iOSDevCamp 2011 Core Data
iOSDevCamp 2011 Core DataiOSDevCamp 2011 Core Data
iOSDevCamp 2011 Core DataChris Mar
 
Core data orlando i os dev group
Core data   orlando i os dev groupCore data   orlando i os dev group
Core data orlando i os dev groupAndrew Kozlik
 
Core Data with Swift 3.0
Core Data with Swift 3.0Core Data with Swift 3.0
Core Data with Swift 3.0Korhan Bircan
 
Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test DriveGraham Lee
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Mobivery
 
Core Data Migration
Core Data MigrationCore Data Migration
Core Data MigrationMonica Kurup
 
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCABeginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCAWhymca
 
Core Data Performance Guide Line
Core Data Performance Guide LineCore Data Performance Guide Line
Core Data Performance Guide LineGagan Vishal Mishra
 
Intro to Core Data
Intro to Core DataIntro to Core Data
Intro to Core DataMake School
 
MobileCity:Core Data
MobileCity:Core DataMobileCity:Core Data
MobileCity:Core DataAllan Davis
 
Connecting to a REST API in iOS
Connecting to a REST API in iOSConnecting to a REST API in iOS
Connecting to a REST API in iOSgillygize
 
Simpler Core Data with RubyMotion
Simpler Core Data with RubyMotionSimpler Core Data with RubyMotion
Simpler Core Data with RubyMotionStefan Haflidason
 
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...smn-automate
 
Writing native bindings to node.js in C++
Writing native bindings to node.js in C++Writing native bindings to node.js in C++
Writing native bindings to node.js in C++nsm.nikhil
 
REST/JSON/CoreData Example Code - A Tour
REST/JSON/CoreData Example Code - A TourREST/JSON/CoreData Example Code - A Tour
REST/JSON/CoreData Example Code - A TourCarl Brown
 
Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...
Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...
Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...Denis_infinum
 
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.pptDESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.pptAntoJoseph36
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012Amazon Web Services
 
10 tips for a reusable architecture
10 tips for a reusable architecture10 tips for a reusable architecture
10 tips for a reusable architectureJorge Ortiz
 

Similar to Core Data with multiple managed object contexts (20)

iOSDevCamp 2011 Core Data
iOSDevCamp 2011 Core DataiOSDevCamp 2011 Core Data
iOSDevCamp 2011 Core Data
 
Core data orlando i os dev group
Core data   orlando i os dev groupCore data   orlando i os dev group
Core data orlando i os dev group
 
Core Data with Swift 3.0
Core Data with Swift 3.0Core Data with Swift 3.0
Core Data with Swift 3.0
 
Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test Drive
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV) Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
 
Core Data Migration
Core Data MigrationCore Data Migration
Core Data Migration
 
Core data optimization
Core data optimizationCore data optimization
Core data optimization
 
Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCABeginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
 
Core Data Performance Guide Line
Core Data Performance Guide LineCore Data Performance Guide Line
Core Data Performance Guide Line
 
Intro to Core Data
Intro to Core DataIntro to Core Data
Intro to Core Data
 
MobileCity:Core Data
MobileCity:Core DataMobileCity:Core Data
MobileCity:Core Data
 
Connecting to a REST API in iOS
Connecting to a REST API in iOSConnecting to a REST API in iOS
Connecting to a REST API in iOS
 
Simpler Core Data with RubyMotion
Simpler Core Data with RubyMotionSimpler Core Data with RubyMotion
Simpler Core Data with RubyMotion
 
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
 
Writing native bindings to node.js in C++
Writing native bindings to node.js in C++Writing native bindings to node.js in C++
Writing native bindings to node.js in C++
 
REST/JSON/CoreData Example Code - A Tour
REST/JSON/CoreData Example Code - A TourREST/JSON/CoreData Example Code - A Tour
REST/JSON/CoreData Example Code - A Tour
 
Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...
Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...
Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...
 
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.pptDESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
DESIGNING A PERSISTENCE FRAMEWORK WITH PATTERNS.ppt
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
 
10 tips for a reusable architecture
10 tips for a reusable architecture10 tips for a reusable architecture
10 tips for a reusable architecture
 

Recently uploaded

Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 

Core Data with multiple managed object contexts

  • 1. Core Data with multiple managed object contexts Photo by Free-Photo-Gallery.org
  • 2. Core Data with multiple managed object contexts Photo by Free-Photo-Gallery.org
  • 3. Matt(hew) Morey Senior Developer at ChaiONE Traveler Boardsport Junkie matthewmorey.com | @xzolian
  • 4. Agenda 1)Core Data Basics 2)Concurrency Problems 3)Concurrency Solutions
  • 5. Agenda 1)Core Data Basics 2)Concurrency Problems 3)Concurrency Solutions
  • 7. Basics App NSManagedObject NSManagedObjectContext NSPersistentStoreCoordinator NSManagedObjectModel NSPersistentStore SQLite XML Binary In Memory Custom
  • 8. Basics App NSManagedObject NSManagedObjectContext NSPersistentStoreCoordinator NSManagedObjectModel NSPersistentStore SQLite XML Binary In Memory Custom
  • 11. Managed Object Model - (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel != nil) { return _managedObjectModel; } NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"core-data" withExtension:@"momd"]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return _managedObjectModel; }
  • 13. Persistent STore Coordinator - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"core-data.sqlite"]; NSError *error = nil; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { /* Replace this implementation with code to handle the error appropriately. ... */ NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return _persistentStoreCoordinator; }
  • 14. Persistent STore Coordinator - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"core-data.sqlite"]; NSError *error = nil; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { /* Replace this implementation with code to handle the error appropriately. ... */ NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return _persistentStoreCoordinator; }
  • 16. Managed Object Context - (NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext != nil) { return _managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { _managedObjectContext = [[NSManagedObjectContext alloc] init]; [_managedObjectContext setPersistentStoreCoordinator:coordinator]; } return _managedObjectContext; }
  • 19. Single Context Code Example https://github.com/mmorey/CoreDataMultiContext/tree/blocking
  • 20. Agenda 1)Core Data Basics 2)Concurrency Problems 3)Concurrency Solutions
  • 21. Problems ‣Core Data Managed Objects are not thread safe ‣Must pass Object IDs to use across threads ‣Objects are locked for all operations including read ‣Objects that feed the UI must be fetched on the main thread
  • 22. Agenda 1)Core Data Basics 2)Concurrency Problems 3)Concurrency Solutions
  • 23. Traditional Multi-Context Pre-iOS 5: Thread Confinement ‣Single NSMangedObjectContext per thread ‣Manual notifications, merging, and saving ‣Fairly easy to understand, but harder to manage
  • 25. Traditional Multi-Context - (void)loadData{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ // Create temp context NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; [context setPersistentStoreCoordinator:[(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator]]; // // Do lots of async work here // // Save the context. error = nil; if (![context save:&error]) { // Replace this implementation with code to handle the error appropriately. abort(); } }); } // Register for save notification in ViewDidLoad [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:context];
  • 26. Traditional Multi-Context - (void)loadData{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ // Create temp context NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; [context setPersistentStoreCoordinator:[(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator]]; // // Do lots of async work here // // Save the context. error = nil; if (![context save:&error]) { // Replace this implementation with code to handle the error appropriately. abort(); } }); } // Register for save notification in ViewDidLoad [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:context];
  • 27. Traditional Multi-Context - (void)loadData{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ // Create temp context NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init]; [context setPersistentStoreCoordinator:[(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator]]; // // Do lots of async work here // // Save the context. error = nil; if (![context save:&error]) { // Replace this implementation with code to handle the error appropriately. abort(); } }); } // Register for save notification in ViewDidLoad [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:context];
  • 28. Traditional Multi-Context - (void)contextDidSave:(NSNotification *)notification { dispatch_async(dispatch_get_main_queue(), ^{ NSManagedObjectContext *mainContext = [self.fetchedResultsController managedObjectContext]; [mainContext mergeChangesFromContextDidSaveNotification:notification]; }); } // Or - (void)contextDidSave:(NSNotification *)notification { [self.managedObjectContext performSelectorOnMainThread: @selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:NO]; }
  • 29. Traditional Multi-Context - (void)contextDidSave:(NSNotification *)notification { dispatch_async(dispatch_get_main_queue(), ^{ NSManagedObjectContext *mainContext = [self.fetchedResultsController managedObjectContext]; [mainContext mergeChangesFromContextDidSaveNotification:notification]; }); } // Or - (void)contextDidSave:(NSNotification *)notification { [self.managedObjectContext performSelectorOnMainThread: @selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:NO]; }
  • 30. Traditional Multi-Context Code Example https://github.com/mmorey/CoreDataMultiContext/tree/notification-context
  • 31. Parent Child Context ≥ iOS 5: Parent Child Contexts ‣Grand Central Dispatch private dispatch queues ‣Threading managed for you, no manual synchronization required ‣Less complicated and more flexible than pre-iOS 5 method ‣Context can and should be nested
  • 32. Concurrency Types NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; ‣NSConfinementConcurrencyType ‣Separate contexts for each thread ‣Default, Legacy option ‣NSPrivateQueueConcurrencyType ‣MOC maintains private serialized queue ‣Can be created from any other thread ‣Idle queues are more efficient than extra threads ‣NSMainQueueConcurrencyType ‣Similar to private queue but on the main queue
  • 35. Parent Child Context __block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; temporaryContext.parentContext = managedObjectContext; [temporaryContext performBlock:^{ // // Do lots of async work here // // Save the context. NSError *error = nil; if (![temporaryContext save:&error]) {abort();} [managedObjectContext performBlock:^{ // Save the context. NSError *error = nil; if (![managedObjectContext save:&error]) {abort();} }]; // main }]; // temp context
  • 36. Parent Child Context __block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; temporaryContext.parentContext = managedObjectContext; [temporaryContext performBlock:^{ // // Do lots of async work here // // Save the context. NSError *error = nil; if (![temporaryContext save:&error]) {abort();} [managedObjectContext performBlock:^{ // Save the context. NSError *error = nil; if (![managedObjectContext save:&error]) {abort();} }]; // main }]; // temp context
  • 37. Parent Child Context __block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; temporaryContext.parentContext = managedObjectContext; [temporaryContext performBlock:^{ Private Queue save // // Do lots of async work here // propagates up to parent // Save the context. NSError *error = nil; if (![temporaryContext save:&error]) {abort();} [managedObjectContext performBlock:^{ // Save the context. NSError *error = nil; if (![managedObjectContext save:&error]) {abort();} }]; // main }]; // temp context
  • 38. Parent Child Context __block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; temporaryContext.parentContext = managedObjectContext; [temporaryContext performBlock:^{ Save to disc still locks PS // which will block the UI during // Do lots of async work here // read operations // Save the context. NSError *error = nil; if (![temporaryContext save:&error]) {abort();} [managedObjectContext performBlock:^{ // Save the context. NSError *error = nil; if (![managedObjectContext save:&error]) {abort();} }]; // main }]; // temp context
  • 39. Basics App NSManagedObject NSManagedObjectContext NSPersistentStoreCoordinator NSManagedObjectModel NSPersistentStore SQLite XML Binary In Memory Custom
  • 40. Async Saving - Parent Child Context
  • 41. Async Saving - Parent Child Context // Child context - (NSManagedObjectContext *)managedObjectContext{ if (_managedObjectContext != nil) { return _managedObjectContext; } _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; _managedObjectContext.parentContext = [self writerManagedObjectContext]; return _managedObjectContext; } // Parent context - (NSManagedObjectContext *)writerManagedObjectContext{ if (_writerManagedObjectContext != nil) { return _writerManagedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { _writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType]; [_writerManagedObjectContext setPersistentStoreCoordinator:coordinator]; } return _writerManagedObjectContext; }
  • 42. Async Saving - Parent Child Context // Child context - (NSManagedObjectContext *)managedObjectContext{ if (_managedObjectContext != nil) { return _managedObjectContext; } _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; _managedObjectContext.parentContext = [self writerManagedObjectContext]; return _managedObjectContext; } // Parent context - (NSManagedObjectContext *)writerManagedObjectContext{ if (_writerManagedObjectContext != nil) { return _writerManagedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { _writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType]; [_writerManagedObjectContext setPersistentStoreCoordinator:coordinator]; } return _writerManagedObjectContext; }
  • 43. Async Saving - Parent Child Context // Child context - (NSManagedObjectContext *)managedObjectContext{ if (_managedObjectContext != nil) { return _managedObjectContext; } _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; _managedObjectContext.parentContext = [self writerManagedObjectContext]; return _managedObjectContext; } // Parent context - (NSManagedObjectContext *)writerManagedObjectContext{ if (_writerManagedObjectContext != nil) { return _writerManagedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { _writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType]; [_writerManagedObjectContext setPersistentStoreCoordinator:coordinator]; } return _writerManagedObjectContext; }
  • 44. Parent Child Context __block NSManagedObjectContext *writerObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] writerManagedObjectContext]; __block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; __block NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; temporaryContext.parentContext = managedObjectContext; [temporaryContext performBlock:^{ // // Do lots of async work here // [temporaryContext save:&error]; {abort();} // Save the context. [managedObjectContext performBlock:^{ [managedObjectContext save:&error]; {abort();} // Save the context. [writerObjectContext performBlock:^{ [writerObjectContext save:&error]; {abort();} // Save the context. }]; // writer }]; // main }]; // temp context
  • 45. Parent Child Context __block NSManagedObjectContext *writerObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] writerManagedObjectContext]; __block NSManagedObjectContext *managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; __block NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; temporaryContext.parentContext = managedObjectContext; [temporaryContext performBlock:^{ NSPrivateQueueConcurrencyType // // Do lots of async work here // NSMainQueueConcurrency [temporaryContext save:&error]; {abort();} // Save the context. [managedObjectContext performBlock:^{ [managedObjectContext save:&error]; {abort();} // Save the context. [writerObjectContext performBlock:^{ [writerObjectContext save:&error]; {abort();} // Save the context. }]; // writer }]; // main }]; // temp context
  • 46. Asynchronous Saving - Parent Child Context Code Example https://github.com/mmorey/CoreDataMultiContext/tree/parent-context
  • 48. Still Blocking? Small and frequent saves during import
  • 49. Still Blocking? Wait for opportunity when user won’t notice
  • 51. Still Blocking? NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"sections" cacheName:@"default-cache"];
  • 52. Still Blocking? For VERY LARGE amounts of data it may be better to generate the SQLite file on the server, download it asynchronously, and set it up as an additional persistent store.
  • 53. References Nested MOC Release Notes: http://developer.apple.com/library/mac/#releasenotes/DataManagement/RN-CoreData/index.html Core Data Programming Guide: http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.html Cocoanetics Blog: http://www.cocoanetics.com/2012/07/multi-context-coredata/ http://www.cocoanetics.com/2013/02/zarra-on-locking/
  • 54. Thanks! Questions? Get in Touch. Twitter: @xzolian App.net: @morey Email: matt@matthewmorey.com URL: http://matthewmorey.com