96
votes

Been having my first crack at Core Data and I'm getting the following error when running my code on my device, but it works fine on the simulator..

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model'

Some of my methods that might be causing the problem:

    - (NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext != nil)
    {
        return __managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        __managedObjectContext = [[NSManagedObjectContext alloc] init];
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return __managedObjectContext;
}

/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created from the application's model.
 */
- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil)
    {
        return __managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"RugbyOnTv" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
    return __managedObjectModel;
}

/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"RugbyOnTV.sqlite"];

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];    
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];


    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return __persistentStoreCoordinator;
}


    - (NSString *)applicationDocumentsDirectory {

        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
        return basePath;
    }

EDIT

I copied and pasted the managedObjectContext method (below) from Apple's CoreDataBooks and it now works..Not really sure why though

- (NSManagedObjectModel *)managedObjectModel {
    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}
27
Hey it could be as simple as appending the word "Model" to the first URLForResource parameter....yeah, I had the same problem. Then I checked the actual .app contents in the command line and found out that the .momd was actually being created. So try this: [[NSBundle mainBundle] URLForResource:@"RugbyOnTvModel" withExtension:@"momd"];PostCodeism
NSString *basePath = [paths firstObject];William Entriken

27 Answers

157
votes

I had exactly the same error message as the original post. I was wrestling with this for hours. It was this line in my AppDelegate.m.

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"[same with name of xcdatamodeld]" withExtension:@"momd"];

For anyone out there searching this error message and finding this thread....try this first.

You must make sure that where it says [same with name of xcdatamodeld]....that it is!!! For some reason, mine had my project name in there and not the data model name.

Changed it and it worked straight away.....

Thanks to Rock & Muller for contributing.......you saved me days!!

Gaz.

54
votes

first verify:

NSLog(@"%@", [self managedObjectModel]);

If you get a nil value maybe the problem is here

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"RugbyOnTv" withExtension:@"momd"];

So, try changing @"momd" by @"mom"

20
votes

I've experienced a weird issue with Xcode 4.3.2 and iOS 5.

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"NAME_OF_THE_MODEL" withExtension:@"momd"];

returns a valid URL but

__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

returns a null NSManagedObjectModel. But after checking the documentation, it seems like NSManagedObjectModel needs a file where as NAME_OF_THE_MODEL.momd is a directory which contains a NAME_OF_THE_MODEL.mom file. Changing the URL to

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"NAME_OF_THE_MODEL" withExtension:@"mom" subdirectory:@"NAME_OF_THE_MODEL.momd"];

then works. Seems weird though that Xcode generates code that doesn't work with itself...

19
votes

I had this problem and changing "moms" to "mom" didn't do anything. To fix it I had to right click on the xcdatamodelId file > show package contents then delete the hidden .xcurrentversion file.

P.S: This problem only started happening after I'd changed the name of the data model file.

13
votes

Another source of this error, is that sometimes Xcode doesn't include the data model in the build.

Check the Build Phases of your target, and ensure that the *.xcdatamodeld file is included in the Compile Sources section.

9
votes

What's probably happened is that your xcdatamodeld file from Apple's source code has turned into a xcdatamodel(without the d) file and therefore they aren't considered the same.

The quickest way to fix this, is to select the xcdatamodel file in your project navigator and in to the menu bar

Editor->Add Model Version...

and add a new version of your model. Make all changes to the new version.

This works in Xcode 5

9
votes

I solve it by adding the db file to the Copy Bundle Resources.

Go to root of your project >> select your target >> Build Phases >> Copy Bundle Resources . Make sure your xcdatamodeld file has been added here.

enter image description here

None of the posted solutions worked for me. So, hopefully this post helps someone out there. My app only crashes in release builds btw. Lesson learned. Always test release builds!

BTW, I found this SO post the most helpful https://stackoverflow.com/a/6708837/951349 .

6
votes

i got same issue with @Dominic Williams

try to change the momd file name in below(you can find this in managedObjectModel method in default), which as same as the [file name].xcdatamodeld file you created:

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"[same with name of xcdatamodeld]" withExtension:@"momd"];
5
votes

I had the same problem. The solution was a mix of 2 answers:

1) I had to add the "subdirectory" parameter into the URLForResource call

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"DATAMODEL_NAME" withExtension:@"mom" subdirectory:@"DATAMODEL_NAME.momd"];

2) For a reason I don't know, the data model was not included when the project was compiled. I had to add it manually into the "Build Phases / Compile resources".

With only one of the above solutions, my application didn't work.

4
votes

The solution to the problem you speak of is simple. Change the file extension to "mom" instead of "momd" in the model URL. Done.

4
votes

I tried all the solutions here, and none of them worked. My issue appeared after I renamed the project. Apparently, Xcode continues to look for the old momd file in the wrong place during compilation.

For anyone that tried all the above solutions without success, try checking the full path of your .xcdatamodeld file. That's what worked for me.

4
votes

I had the same problem, it worked fine on iOS6 but not on iOS5. This is how I solved it:

  1. Create a new Model version in xcode. (select the .xcdatamodeld, open the Editor menu and click "Add Model Version...")
  2. Compile and make sure that the new version works.
  3. Set the old one as current version. ("Current" in File Inspector for the .xcdatamodeld under Versioned Core Data Model)
  4. Remove reference to the .xcdatamodeld file in xcode
  5. Right click the .xcdatamodeld file in Finder and choose "Show Package Contents"
  6. Delete the new .xcdatamodel that you dont want
  7. Re-add the .xcdatamodeld in xcode
  8. Compile and smile

(This is where I found how to delete a Model version: How to delete an old/unused Data Model Version in Xcode)

4
votes

I solve the problem without changing any code.

I add the ModelName.xcdatamodeld through File->Add File instead of dragging the file into the Xcode.

 NSString *path=@"ModelName";

NSURL *modelURL = [NSURL fileURLWithPath:[path stringByAppendingPathExtension:@"momd"]];

model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
1
votes

On my side the problem was that I'd changed the case of a couple of characters in the database name.

When starting a new project, Xcode automatically sets everything up from the project name. If you started out calling your project "Rugbyontv" and later decided to change to "RugbyOnTV" and did a search and replace, that would break it. (Credit to Rob for pointing out that the name is case-sensitive)

1
votes

I have been looking an answer for hours and nothing worked. But then I suddenly found this article. So according to this, the problem was in setting root controller in this part of AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    ListViewController *rootView = (ListViewController *)self.window.rootViewController;
    rootView.managedObjectContext = self.managedObjectContext;
    return YES;
}

In fact you should define what root controller will delegate your CoreData connection. And in my case I had a TabBarController connected to other views, so my targed view root controller was defined as TabBar and it caused an error. I changed

ListViewController *rootView = (ListViewController *)self.window.rootViewController;

to

ListViewController *rootView = (ListViewController *)self.window.superview;

and everything worked.

1
votes

I know this doesn't solve your problem but I ran into this problem yesterday that plagued me for hours, the solution @Dominic Williams posted gave me a ArrayIndexOutOfBoundsException (whatever the Objective-C equivalent is).

I'm not very good with Objective-C/Xcode yet but I'm working on an iOS app that our company had (mostly) developed externally. Unfortunately, they would often forget how to use a keyboard and would use capital letters interchangeably or spell properties incorrectly but were too lazy to go back and change it. They had used a capital letter in the xcode project name where it was not supposed to be (our product name doesn't use a capital) and I had to go back and change every occurence of this upper-case letter to a lower-case; which included the project name, core data file, hundreds of variables, etc.

Anyways, once I had done this I ran into this error and no solution was fixing it for me. I had made sure that all URL names were correct, project cleaned, app uninstalled, phone restarted, etc with no avail. I gave up and turned off my Mac and went home for the day. To my surprise, I came back in this morning and everything seemed to work fine!

I have no idea why this worked but if your stuck, try restarting your Mac.

1
votes

If someone is stuck because of the same issue. Make sure you have properly linked the database (as you might have copied the code directly from some example).
Just update the name of the database in managedObjectModel and persistentStoreCoordinator methods in AppDelegate.

1
votes

I had the same issue, i.e.

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyModel" withExtension:@"momd"];

returned nil, because there was no .momd file generated.

The reason was that in the app directory (e.g. MyGreatApp/MyGreatApp.app) xcode had copied the MyModel.xcdatamodeld instead of generating the MyModel.momd from the MyModel.xcdatamodeld file (using momc).

The solution was to delete the reference to MyModel.xcdatamodeld inside the XCode project browser and drag it back into the project from the finder. After that xcode realized it needed to compile it to a .momd.

1
votes

I had this problem out of nowhere after I deleted the generated app in the ~/Library/Application Support/iPhone Simulator. Somehow this caused subsequent builds to fail in the simulator and on devices. Hadn't changed anything to do with CoreData for ages but it would fail with the Cannot create an NSPersistentStoreCoordinator with a nil model . Tried a few things above and nothing worked.

I could see the generated momd folder with the mom file inside. The app in the simulator could see both but it failed to generate the sqlite file.

What solved it was adding an attribute to an entity in my xcdatamodeld file in Xcode and then immediately deleting it. I was hoping this would get Xcode to regenerate whatever was causing the issue from scratch and it seemed to work. Still not clear what was actually wrong, but my app is running in the simulator and devices again now.

0
votes

I just had a similar problem upgrading from IOS5 to IOS6. Turns out it was a case sensitive issue with the model name.

Not sure if this helps anyone.

0
votes

See also this thread: Unit Test can't find Core Data model file

It helped my solving the issue - which occurred only with Unit-Testing

0
votes

Okay, I'll tell a half-solution first, it will work if you re-install the app(in simulator or debugger device). But that's not a real solution for sure. For example, if you are updating your application, do NOT do that or your new version may crash because users won't re-install it, they'll use update button instead.

As I understood, this problem happens mostly when you change the data model file name. The reason might be like this:
. When you run the app for the first time, it is creating a data model file in app bundle like "data_model_1". This creation happens only for first time.
. When you update the file name and run the app again, it won't be able to find because there is still "data_model_1" file but you are telling it to look for "data_model_2". How can it find, it has not created it yet and will not unless you don't install the app with new file name.

So, if this is the first version of your app and re-installing on simulator or device doesn't harm your project, go for it. Else, check Core Data Model Versioning and Data Migration Guide on iOS Developer Library, maybe it's what you need.

Edit: If reinstalling does not work, try uninstalling first, then cleaning project, then close everything, reopen project and build+run. That should work.

0
votes

If your project works on the simulator but not on the device, try running the release-build on your device instead of the debug-build.

Select your project -> Product -> Edit Scheme -> Build Configuration [DEBUG -> RELEASE]

Now run the project again, it will work.

0
votes

I am also facing this problem but when i change the ModelName.xcdatamodeld file it is working. so i think ModelName.xcdatamodeld file not added to properly, so once check and clean the app and run it.

0
votes

After I fixed the naming issue, the error remained. Then it worked after restarting Xcode 5. This might automatically do the same thing as some of the manual linking suggestions offered here.

0
votes

For me the problem was due to the fact that I copy pasted my model from a sandbox project to my actual project. Always make sure to generate your model from within the project that the model is being used.

0
votes

I faced this same error when i renamed the .xcdatamodel file from xcode and changed the renamed name in app delegate wherever it was needed, but i still got the same error. None of the suggested procedure worked for me.

Then I opened the folder in Finder and found an additional file .xccurrentversion along with .xcdatamodel file. I opened it up in TextEdit app and changed this:

<dict>
    <key>_XCCurrentVersionName</key>
    <string>Your_Renamed_Model_FileName.xcdatamodel</string>
</dict>

I am using this with Xcode 6.4, OSX Yosemite 10.10.1

I hope it helps!