TooManyEduardos
TooManyEduardos

Reputation: 4404

iOS - How to Pass AppDelegate's ManagedObjectContext to UIViewController that comes from NavigationView

I'm struggling with a Core Data concept and I need some clarification.

I'm using Storyboards and I have 2 view. The first view is embedded in a navigation controller, and the second view is just a UIViewController that comes from a modal segue. In AppDelegate I am passing the managedObjectContext to the first view using this code:

UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
JobListTableViewController *jltvc = (JobListTableViewController *)[[nav viewControllers]objectAtIndex:0];
jltvc.managedObjectContext = self.managedObjectContext;

The problem is that now I need to also pass the managedObjectContext from AppDelegate to my second view, but I dont know how to get a hold of it. Doing this, just fails since there's no index 1:

AddJobsViewController *ajvc = (AddJobsViewController *)[[nav viewControllers]objectAtIndex:1];

I can't post a screenshot of my storyboard since I dont have enough stackoverflow reputation :(

Any help on this core data/delegation issue will be highly appreciated. Thank you.

Upvotes: 3

Views: 5454

Answers (2)

sanjaymathad
sanjaymathad

Reputation: 232

My suggestion to you is that you don't pass the context from view controllers. Rather than that create a new context and fetch the entities from the new context. The downside of passing the same context is that if a same entity is modified in two different places, you have to manage the merge conflict. Context is like a scrap pad that can be used to either make changes and save or else discard the context if you don't want changes. So you can create a local context every time you want to modify the entities and either save or discard it depending on your needs and hence avoiding conflicts. what i prefer is a 3 tier system like this

-(NSManagedObjectContext*) backgroundMasterContext // this context is used to save data in core data
{
    if(!_backgroundMasterContext) {
        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if(coordinator) {
            _backgroundMasterContext =  [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
            [_backgroundMasterContext setPersistentStoreCoordinator:coordinator];
        }
    }
    return _backgroundMasterContext;
}

-(NSManagedObjectContext*) mainContext // this context is a read only context which is used everytime you want to read the entities
{
    if (!_mainContext) {
        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if (coordinator) {
            _mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
            [_mainContext setParentContext:self.backgroundMasterContext];
        }
    }

    return _mainContext;
}

-(NSManagedObjectContext*) createWriteContext // this context is used everytime you want to edit an entity 
{
    NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [newContext setParentContext:self.mainContext];
    return newContext;
}

And for saving i call this method

- (void) saveAllWithContext:(NSManagedObjectContext*) writeContext
                    success:(DMSuccessBlock)success
                    failure:(DMFailureBlock)failure
{
    BOOL b = NO;
    NSError *error = nil;
    if([writeContext hasChanges]) {
        b=[writeContext save:&error];

        if(b) {
            NSManagedObjectContext *parentContext = [writeContext parentContext];
            if(parentContext) {
                [parentContext performBlock:^{
                    [self saveAllWithContext:parentContext success:success failure:failure];
                }];
            } else {
                if(success)
                    success();
            }
        } else {
            if(failure)
                failure(error);
        }
    }
    else {
        if(success)
            success();
    }
}

This method updates main context and background master context.

Hope it helps :)

Upvotes: 0

βhargavḯ
βhargavḯ

Reputation: 9836

In your JobListTableViewController or AddJobsViewController, you can hold reference of AppDelegate like this.

#import "AppDelegate.h"


AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
jltvc.managedObjectContext = app.managedObjectContext;

Upvotes: 6

Related Questions