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

What's hot

9 mod analog_am_fm (1)
9 mod analog_am_fm (1)9 mod analog_am_fm (1)
9 mod analog_am_fm (1)
mirla manama
 
02 feam enclosures_eng
02 feam enclosures_eng02 feam enclosures_eng
02 feam enclosures_eng
Hai Pham
 
Fm radio reciever
Fm radio recieverFm radio reciever
Fm radio reciever
Ashwin HL
 

What's hot (20)

Assignment
AssignmentAssignment
Assignment
 
akbar trading jubail cembre Ring pin blade hooked type lugs
akbar trading jubail cembre Ring pin blade hooked type lugs akbar trading jubail cembre Ring pin blade hooked type lugs
akbar trading jubail cembre Ring pin blade hooked type lugs
 
9 mod analog_am_fm (1)
9 mod analog_am_fm (1)9 mod analog_am_fm (1)
9 mod analog_am_fm (1)
 
Transistors & i cs cross references
Transistors & i cs cross referencesTransistors & i cs cross references
Transistors & i cs cross references
 
Rf design and review guidelines
Rf design and review guidelinesRf design and review guidelines
Rf design and review guidelines
 
Phase shift keying
Phase shift keyingPhase shift keying
Phase shift keying
 
Haberlesme Sistemleri
Haberlesme SistemleriHaberlesme Sistemleri
Haberlesme Sistemleri
 
02 feam enclosures_eng
02 feam enclosures_eng02 feam enclosures_eng
02 feam enclosures_eng
 
Tradicionais
TradicionaisTradicionais
Tradicionais
 
Empire Office Furniture brochure
Empire Office Furniture brochureEmpire Office Furniture brochure
Empire Office Furniture brochure
 
Cataloge schneider acb masterpact
Cataloge schneider acb masterpactCataloge schneider acb masterpact
Cataloge schneider acb masterpact
 
Design
DesignDesign
Design
 
Amplitude modulation
Amplitude modulationAmplitude modulation
Amplitude modulation
 
Esquema receptor century usr1700 cópia
Esquema receptor century usr1700   cópiaEsquema receptor century usr1700   cópia
Esquema receptor century usr1700 cópia
 
Duty Cycle Corrector Using Pulse Width Modulation
Duty Cycle Corrector Using Pulse Width ModulationDuty Cycle Corrector Using Pulse Width Modulation
Duty Cycle Corrector Using Pulse Width Modulation
 
Original N-Channel Mosfet CEP83A3 30V 100A TO-220 New CET
Original N-Channel Mosfet CEP83A3 30V 100A TO-220 New CETOriginal N-Channel Mosfet CEP83A3 30V 100A TO-220 New CET
Original N-Channel Mosfet CEP83A3 30V 100A TO-220 New CET
 
it-lecture-distribution-rev-3-dec-2013.pdf
it-lecture-distribution-rev-3-dec-2013.pdfit-lecture-distribution-rev-3-dec-2013.pdf
it-lecture-distribution-rev-3-dec-2013.pdf
 
Chapter 4 frequency modulation
Chapter 4 frequency modulationChapter 4 frequency modulation
Chapter 4 frequency modulation
 
Fm radio reciever
Fm radio recieverFm radio reciever
Fm radio reciever
 
Mini Project 2 - Frequency Shift Keying (FSK) Modulator and Demodulator
Mini Project 2  -  Frequency Shift Keying (FSK) Modulator and DemodulatorMini Project 2  -  Frequency Shift Keying (FSK) Modulator and Demodulator
Mini Project 2 - Frequency Shift Keying (FSK) Modulator and Demodulator
 

Similar to Core Data with multiple managed object contexts

Beginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCABeginning icloud development - Cesare Rocchi - WhyMCA
Beginning icloud development - Cesare Rocchi - WhyMCA
Whymca
 
MobileCity:Core Data
MobileCity:Core DataMobileCity:Core Data
MobileCity:Core Data
Allan Davis
 
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
AntoJoseph36
 

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
 
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
 

Recently uploaded

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Recently uploaded (20)

Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 

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