SlideShare une entreprise Scribd logo
1  sur  54
Télécharger pour lire hors ligne
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

Contenu connexe

Similaire à 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
 
High Performance Core Data
High Performance Core DataHigh Performance Core Data
High Performance Core DataMatthew Morey
 
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
 

Similaire à 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
 
High Performance Core Data
High Performance Core DataHigh Performance Core Data
High Performance Core Data
 
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
 

Dernier

Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
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
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
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
 
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
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
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
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
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
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
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
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
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
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
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
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 

Dernier (20)

Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
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
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
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
 
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...
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
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
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
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
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
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
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
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.
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
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
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 

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