0

Inside my iOS application, I am using Core Data to do a fetch, and delete of a very large data set. This process takes approximately 5-10 seconds. What I would like to do is perform a rollback in case the user decides to turn the device off before the process has completed. However, the problem is to have the SAME instance of the NSManagedObjectContext to call the rollback function from the appropriate AppDelegate method. Within my application, I call my Core Data methods using a Singleton object like this:

static MySingleton *sharedSingleton = nil;


+ (MySingleton *) sharedInstance {

    if (sharedSingleton == nil) {
        sharedSingleton = [[super alloc] init];
    }
    return sharedSingleton;
}

In my application, I return an instance of an NSManagedObjectContext like this:

- (NSManagedObjectContext *) managedObjectContext{

    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil) {

        _managedObjectContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];

        //Undo Support
        NSUndoManager *anUndoManager = [[NSUndoManager alloc] init];
        [self.managedObjectContext setUndoManager:anUndoManager];
    }
    return _managedObjectContext;
}

I then call it, and assign it to a reference like this:

NSManagedObjectContext *context = [[MySingleton sharedInstance] managedObjectContext];

How would I make this instance of the ManagedObjectContext available to me for use in the AppDelegate, so that I can call the rollback function?

halfer
  • 19,824
  • 17
  • 99
  • 186
syedfa
  • 2,801
  • 1
  • 41
  • 74

2 Answers2

2

First off, the better (safer) way to create a singleton is as in the example given here: Create singleton using GCD's dispatch_once in Objective C, namely:

+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

Next, since you've created a managed object context that must hang around for a few seconds, you must have a strong reference to it somewhere, which you do.

If you're in the midst of debugging and are questioning some fundamental assumptions about your code, give the managed object context a name (or log the memory address of the MOC pointer), that you can inspect in the debugger later, to verify for yourself that indeed, you're dealing with the same one.

Note also that if you created a dedicated Managed Object Context just for this sort of importing, you wouldn't need to roll it back. You could just discard it.

In my apps, I usually have a parent (root) managed object context and a couple of child contexts; one child is for the main thread, another child is for import type operations.

Community
  • 1
  • 1
idStar
  • 10,674
  • 9
  • 54
  • 57
1

As an alternative solution, instead of rollback the changes, you can create a multi context scenario where a child managed object context add all the data that you need and eventually when its done, you save the child context sending the new data to the main managed object. This way the main managed object context its not affected until the complete process is done.

This is a great article as reference Multi-Context CoreData.

Basically what you need to do is

// create main MOC
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainContext setPersistentStoreCoordinator:_persistentStoreCoordinator];

// create child MOC
_childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_childContext.parentContext = _mainContext;

Hope it helps.

Jonathan P. Diaz
  • 3,213
  • 1
  • 18
  • 13