Using mergedModelFromBundles: and versioning (CoreData)
Asked Answered
C

8

10

I'm trying to use the migration feature in CoreData. I've followed the Apple Documentation. I have a problem in the following method:

/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
 */
- (NSManagedObjectModel *)managedObjectModel {

    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    /* 
     * NSInvalidArgumentException', reason: '*** -[NSCFArray insertObject:atIndex:]: attempt to insert nil'
     * 2010-02-17 16:27:15.338 Patrimoine[3037:207]
     */ 
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}

It appears that there is the same problem on http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html

Yet I did choose the method Apple suggests, by using the menu option "Add Model Version".

Do you have any idea?

Conferee answered 17/2, 2010 at 15:50 Comment(0)
T
28

You need to clean your project. As soon as you "version" your model Xcode moves it into a bundle (folder) but it does not remove the old one. What happens then is that the next time you run your app there are two copies of your model in the bundle; the old one and the new one that is inside of the momd bundle.

Doing a Project -> Clean All will resolve this issue.

Transcendentalism answered 17/2, 2010 at 17:16 Comment(1)
Cleaning doesn't necessarily fix the problem. Xcode doesn't remove old resource files from installed apps, even after a clean build. Using initWithContentsOfURL instead of mergedModelFromBundles at least reduces the problem to only old .mom files in the one folder. (I was just fighting this problem for days: https://mcmap.net/q/135136/-the-model-used-to-open-the-store-is-incompatible-with-the-one-used-to-create-the-store)Stonge
R
9

Also, if you rename your models at any point, be sure and repeat the "set current model" step by switching to an older then back to the newer model again. My build setting would not reset itself automatically and kept setting the "current model name" to a nonexistent model, resulting in the exact same problem.

You can always verify this setting is correct in the build product's resource folder, inside the imported .momd directory, in a file called versioninfo.plist - the setting for the current model MUST match the actual name of your model.

Ruy answered 24/3, 2010 at 23:49 Comment(1)
Even after 6 years of paid iOS dev I never knew this xcode bug. Still present in Xcode 6. Thanks heaps!Dorindadorine
S
4

I've found that using the mergedModelFromBundel: method doesn't seem to work with migration; I switched to -initWithContentsOfURL:, and it works fine. Note that you have to init it with a URL pointing to a ".momd" file.

Skeen answered 17/2, 2010 at 15:57 Comment(3)
I get Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot create an NSPersistentStoreCoordinator with a nil model' (the file url is correct). This error happens in: persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];Conferee
There's no need to switch to initWithContentsOfURL:. The issue is, per Marcus' answer, the fact that your build product still contains the old model. It'll be fixed if you simply do a make clean. Using initWithContentsOfURL: works because you're now not picking up the old model.Mensa
Actually, there is a need since Xcode doesn't remove old resource files (see my comment on @Marcus answer).Stonge
F
2

If you change your data model at any point, be sure to Reset Content and Settings in the simulator, or you will get the error that the version of the model used to make the store is not the same as the model used to access it.

Foucquet answered 28/1, 2011 at 2:22 Comment(0)
V
0

Thanks to everyone!

These all worked, but only after I used the Clean build option.

See this other Stack Overflow topic for more info: Using mergedModelFromBundles: and versioning (CoreData)

The iPhone Core Data Reference has a fairly decent write up on this. The formal process from the documentation is an "Automatic Lightweight Migration".

Thanks again, --Batgar

Vite answered 28/2, 2010 at 14:50 Comment(0)
T
0

At first, none of the mentioned methods worked for me. I'm using XCode 4. Performed Clean, Clean Build Folder, located the .app file to check there's no other .xcdatamodel file there except the correct one (containing both old and new versions). Tried to use initWithContentsOfURL:. Verified the current version corresponds to the correct one and did Reset Content and Settings on the simulator. Then edited the VersionInfo.plist and discovered that the NSManagedObjectModel_CurrentVersionName value corresponds to a non-existing version name!

So reset the current version name for some existing model (you then see the green checkmark changing), rebuilt and it worked.

FYI!

Tatterdemalion answered 15/5, 2011 at 11:39 Comment(0)
S
0

Unfortunately for me, it wasn't an issue of cleaning or versioning. I have a somewhat complicated project with several layers of nested Xcode projects. To handle the issue of each project being in different SVN repository, I set up the paths to my projects as relative to some specific source trees that I set up in the Xcode "Preferences --> Locations". For instance, I set up FACEBOOK_IOS_SDK_SRC to point to "~/Documents/{my_crazy_folder_structure}/facebook-ios-sdk/src". This way, whenever my colleagues checkout my project, the location of the Facebook SDK is relative to whatever path they set up and doesn't have to be in the exact same structure on their machines as it is on mine. I know there are better ways to handle this but it is working for now.

Anyways - my issue came up because at some point I had my *.xcdatamodel file location as "Relative to {source_tree_path}", which found the file just fine, and even compiled it into a *.mom file but I was getting this crazy error listed in the initial question. I changed my location to "Relative to Group" and it started working. I haven't found the exact reason for this yet but it wasted the better part of a day investigating. Hopefully this will help someone else out in the future.

Safe answered 20/3, 2012 at 11:7 Comment(0)
W
0

I started getting crashes for [[NSManagedObjectModel mergedModelFromBundles:nil] as well, with no error message (typical core data). I eventually solved it by realising that I had named two entities in different models with the same name. That is why it was crashing for me. Changing the names stopped it crashing.

Wrightson answered 11/9, 2015 at 10:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.