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 NSPredicate
s 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.
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];