Kenny Wyland
Kenny Wyland

Reputation: 21870

Importing old CoreData model into new project

I have an old Xcode project which contains a CoreData model (containing a version 1 and version 2 of the model). For several reasons I need to create a new Xcode project and transfer all of the code to the new project.

How can I import/transfer my old CoreData model in such a way that this new binary will still be able to read, and potentially migrate, the existing CoreData stores which are on my existing users' iPhones and iPads out in the world? I worry that if I push a new version using this new project that my users will update their app to the newest version and then it'll crash because the model or model version numbers don't match.

I'm NOT talking about adding a new version to the data model within the same app. I understand that process. This is about moving/importing/etc an existing data model from an old project into a new project.

Should I just copy the files over and add them to my project manually? Do I need to change things in my build settings to account for it?

Upvotes: 13

Views: 7402

Answers (3)

curt
curt

Reputation: 4582

I found a simpler way. I created a new project with core data and then closed it without building or running it. I then used an IDE to open the xcdatamodeld. A text editor would probably work just as well. I had to drill down to the content. This may be because I'm using PHPStorm and it's trying to make a project out of this. The file that I wanted to edit looked like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"   lastSavedToolsVersion="1" systemVersion="11A491" minimumToolsVersion="Automatic"   sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
</model>

I then opened the source xcdatamoleld and copied every thing between the model tags to the new file. I closed the files and built the project. I didn't copy the actual model data (.storedata).

One caveat: In my original project, I was constantly changing the model and deleting the model data. Xcode couldn't handle it and threw off various errors. The last time I did it, I got the warning:

CoreData: warning: Unable to load class named 'Performance' for entity 'Performance'.  Class not found, using default NSManagedObject instead.

This warning reoccured in the new project so it's something wrong in the model definition. Fortunately, it doesn't cause any problems with the execution. If you don't have this warning, you may be fine.

This was with Xcode 8.2.1 and it was a Swift project.

Upvotes: -1

Kenny Wyland
Kenny Wyland

Reputation: 21870

In the end, this is how I solved it:

  1. Create new project with CoreData
  2. Copy the raw CoreData model file over into my new project. Add it to the project.
  3. Delete the empty CoreData model autocreated by the new project.
  4. In the Project Settings, under Build Phases, Compile Sources, I added the copied CoreData model file.

Then I used the code that Scott provided above:

[NSManagedObjectModel mergedModelFromBundles:nil]

which automatically finds all of the models and combines them. By deleting the auto-generated one and adding my transferred one then everything works out just fine.

Upvotes: 12

Scott Corscadden
Scott Corscadden

Reputation: 2860

As long as you keep the same application identifier, your new code will replace the binary for installed users while keeping all their data there untouched. So your new project essentially swaps in as a new binary. After that, it's up to you to make sure you load the right .sqlite file, handle the upgrades, etc.

Let me edit this a bit further. Downvote has a sad.

There is a ZMETADATA table (or equivalent, can't get to that now) that has all the information necessary to identify things. Further there is hashes to know whether the current versions are present such that automatic migration can happen. Provided the hashes exist, and that you've loaded your model via [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:modelPath]] instead of [NSManagedObjectModel mergedModelFromBundles:nil], then all should be well.

Upvotes: 2

Related Questions