Search code examples
ioscore-datansmanagedobjectcontext

managedObjectContext unrecognized selector sent to instance


I am following a tutorial to develop an iOS app. I am using core data. The first view of the app is RootViewController. All Core Data stack is on the AppDelegate file. This is the part of the code from AppDelegate.m that makes the call to the RootViewController file:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // Fetch the data to see if we ought to pre-populate
  NSError *error = nil;
  if (![[self fetchedResultsController] performFetch:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
  }

  [self loadFavoriteThingsData];        

  RootViewController *rootViewController = (RootViewController *)[navigationController topViewController];
  [rootViewController setManagedObjectContext:[self managedObjectContext]];       

  [window addSubview:[navigationController view]];
  [window makeKeyAndVisible];
  return YES;
}

Now, in another part of the app I need to open a new view Controller that is a duplicate of RootViewController, called DoneViewController, but using other NSPredicates to show other core data objects.

In RootViewController there is a button to open the MenuViewController file, from there I try to open DoneViewController using following method:

- (IBAction)doneToDoaction:(id)sender {
    DoneViewController *viewController = [[DoneViewController alloc] init];

    [self presentViewController:viewController animated:YES completion:nil];
}

but an exception is fired:

[MenuViewController managedObjectContext]: unrecognized selector sent to instance 0x145a0c00
2013-12-26 22:58:23.688  *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MenuViewController managedObjectContext]: unrecognized selector sent to instance

I guess I have to pass the managedObjectContext from RootViewController to MenuViewController and then from MenuViewController to DoneViewController, but I don't know how to do it.


Solution

  • There are few solutions to do what you want.

    The first is to expose the context from the application delegate as @Gyanendra commented. The second is to pass the context from controller to controller. For further references I really suggest to read PASSING AROUND A NSMANAGEDOBJECTCONTEXT ON IOS by Marcus Zarra.

    Anyway, I would prefer the second solution. Passing around the context or grabbing by an instance of NSManagedObject. Based on the latter each NSManagedObjectInstance has a reference to the context has been registered in.

    [managedObjectInstance managedObjectContext];
    

    These solutions prevent to have a rigid application and avoid to pollute the application delegate.

    In your case, you could just follow this approach. From RootViewController pass the context to MenuViewController and then, from the latter, pass it to DoneViewController. How?

    Simple enough. Just expose properties like for the controller you are interested in (MenuViewController and DoneViewController in this case).

    @property (nonatomic, strong) NSManagedObjectContext* mainContext;
    

    that can be set as

    // from RootViewController
    menuViewController.mainContext = [self managedObjectContext];