Core-Data iPhone: could not locate an NSManagedObjectModel

I am using Apple's CoreDataBooks sample project as a learning aid for core data.

I modified the app so that when the app loads I show a menu page first - not the Books tableview (RootViewController).

I have done the following:

I created a menu page in interface builder (just a view with a button on it)

The CoreDataBooksAppDelegate.h now looks like this:

// for the menu
@class MenuViewController;

@interface CoreDataBooksAppDelegate : NSObject <UIApplicationDelegate> {

NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;     
NSPersistentStoreCoordinator *persistentStoreCoordinator;

UIWindow *window;
UINavigationController *navigationController;

//for the menu
MenuViewController *viewController;
}

- (IBAction)saveAction:sender;

//for the menu
@property (nonatomic, retain) IBOutlet MenuViewController *viewController;

@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator     *persistentStoreCoordinator;

@property (nonatomic, readonly) NSString *applicationDocumentsDirectory;

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;

@end

The CoreDataBooksAppDelegate.m looks like this:

#import "CoreDataBooksAppDelegate.h"
#import "RootViewController.h"
// for the menu
#import "MenuViewController.h"


@implementation CoreDataBooksAppDelegate

@synthesize window;
@synthesize navigationController;

// for the menu
@synthesize viewController;


#pragma mark -
#pragma mark Application lifecycle

- (void)applicationDidFinishLaunching:(UIApplication *)application {

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

// for the menu
[window addSubview:viewController.view];

// Configure and show the window
[window makeKeyAndVisible];
}

The rest of CoreDataAppDelegete.m remains unchanged.

In the MenuViewController when the button is clicked, the following action takes place:

RootViewController *modalViewController1 = [[[RootViewController alloc] initWithNibName:nil bundle:nil] autorelease];  
[self presentModalViewController:modalViewController1 animated:YES];

In IB I changed the MainWindow.xib to call the MenuViewController rather than the RootViewController.

So, the app loads and the menu is displayed properly with the button. Upon clicking the button the application crashes inside of the RootViewController's viewDidLoad.

It crashes right here:

- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1 START viewDidLoad RootViewController");
self.title = @"Books";
// Set up the edit and add buttons.
self.navigationItem.leftBarButtonItem = self.editButtonItem;

NSLog(@"2 setup button viewDidLoad RootViewController");
// Configure the add button.
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]   initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self   action:@selector(addBook)];
self.navigationItem.rightBarButtonItem = addButton;
[addButton release];  

NSLog(@"3 viewDidLoad RootViewController");
NSError *error;
// HERE IS THE CRASH SITE
 if (![[self fetchedResultsController] performFetch:&error]) {
  NSLog(@"Does not reach this point in viewDidLoad RootViewController");
  // Update to handle the error appropriately.
  NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
  abort();  // Fail
 }
 NSLog(@"END viewDidLoad RootViewController");
}

In the console I receive the following:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'Book''

I have read about this exception but I do not know the proper steps to resolve it.


Solution 1:

Ok.

Placing the following code inside of the RootViewController's viewDidLoad eliminates the error:

if (managedObjectContext == nil) 
{ 
    managedObjectContext = [(CoreDataBooksAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
    NSLog(@"After managedObjectContext: %@",  managedObjectContext);
}

I found someone with a similar problem here on SO: link text

As Aryeh pointed out in that post: "In short you are trying to fetch an entity from an objectContext that hadn't been set up yet. Your options therefore are to set it up right then or do elsewhere in the app before this view loads."

Solution 2:

In applicationDidFinishLaunching: you're doing the following:

rootViewController.managedObjectContext = self.managedObjectContext;

But I don't see the code where self.managedObjectContext is setup. applicationDidFinishLaunching is called pretty early on. Are you sure you setup the managed object context?

Solution 3:

Did you change the Core Data model at all? That error is common when the Core Data model for an app changes without also changing the underlying SQLite database, so the stored data and the model are out of sync.

Try completely removing your app from the Simulator or testing device, then reinstalling it and trying again.