2

Hi I am trying to set my UIViewController's managed object context, but the object context is not saved. Here's the code:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
my_TableViewController *viewController = [mainStoryboard instantiateViewControllerWithIdentifier:@"coretut"];
if ([viewController isKindOfClass:[my_TableViewController class]]) {
    [viewController setOManagedObjectContext:self.managedObjectContext];
}
NSLog(@"%@", self.managedObjectContext);
NSLog(@"%@", viewController.oManagedObjectContext);
}

The output for the following is

Apple_Tutorial[11241:461826] <NSManagedObjectContext: 0x7fb558d86600>
Apple_Tutorial[11241:461826] <NSManagedObjectContext: 0x7fb558d86600>

However when i call

NSLog(@"%@", self.oManagedObjectContext);

In viewDidLoad() for my_TableViewController the output is null. oManagedObjectContext is declared as (strong, nonatomic). Does anyone know why oManagedObjectContext went to null?

viewDidLoad code:

- (void)viewDidLoad {
    [super viewDidLoad];
    UINib *nib = [UINib nibWithNibName:@"my_TableViewCell" bundle:nil];
    [[self tableView] registerNib:nib forCellReuseIdentifier:@"tableViewCell"];

    NSLog(@"%@", self.oManagedObjectContext);
}
Python Lord
  • 341
  • 2
  • 4
  • 15

1 Answers1

2

The problem is that didFinishLaunchingWithOptions is instantiating a new view controller and then doing nothing with it (i.e. discarding it). So you're looking at two different view controller instances.


You might have the app delegate set the root view controller's oManagedObjectContext:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ViewController *controller = (id)self.window.rootViewController;
    NSAssert([controller isKindOfClass:[ViewController class]], @"Root controller should be `ViewController`, but is %@", controller);

    controller.oManagedObjectContext = self.managedObjectContext;

    return YES;
}

Clearly, if your view controller in question isn't the root controller (e.g. if it's in some container view controller, such as navigation controller, tab bar controller, custom container controller, etc.) then you'd have to tweak the above code to navigate through that hierarchy to find your view controller class.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    This answer says that apple discourages using that method. [http://stackoverflow.com/questions/7799625/get-nsmanagedobjectcontext-when-using-storyboard] Is there anyway to keep the old view controller that I instantiated? – Python Lord Jun 26 '15 at 06:18
  • ^ agreed. "When you create a view controller, you pass it a context. You pass an existing context, or (in a situation where you want the new controller to manage a discrete set of edits) a new context that you create for it. It’s typically the responsibility of the application delegate to create a context to pass to the first view controller that’s displayed." From [the Apple Documentation](https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html) – jperl Jun 26 '15 at 06:19
  • 1
    Good point. And Apple is correct on this point, that its almost always better to pass the necessary information _to_ the view controller rather than pulling it _from_ the app delegate. It doesn't have a material impact here, but it is the right way to do it. I've modified my answer accordingly. – Rob Jun 26 '15 at 15:10