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?
In the end, this is how I solved it:
Create new project with CoreData
Copy the raw CoreData model file over into my new project. Add it to the project.
Delete the empty CoreData model autocreated by the new project.
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.
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.
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.
Related
I have a first version of an iOS app written in Objective-C using core data.
I am now in the process of totally re-writing the app from scratch in Swift because the Objective-C version is very buggy.
The goal is to keep the database content in the app, after updating from Objective-C to Swift version. Users should not lose data.
In the Swift project, I used the .xcdatamodel that was automatically generated and I recreated all Entities and Relationships exactly based on the Obj-c .xcdatamodel file.
Bunddle identifier is the same for both version. In the simulator, one is replacing the other when I run projects. But the database is erased each time.
I found several topics explaining lightweight or heavy migration, but always related to a data model change inside the same project.
Is it possible to copy the old .xcdatamodel file into the new project?
I tried but without any success. Maybe problems are that files are named differently and that projects are written in different languages.
Copying a model file to a new project is literally as simple as copying the file.
If you have both Xcode projects open, you can drag the file from one project into the other. Xcode will ask what you want to do-- make sure that "Copy items if needed" is checked. Click "Finish" and you're done.
Or do it in Finder. Duplicate the old file, move the duplicate into the new project's folder, and rename it if necessary. Then switch to Xcode and tell it to add the new model file ("File" menu --> "Add files...").
I have an existing project we'll call ABC.
I have a new project we'll call XYZ.
All I'm trying to do is copy the MyDataModel.xcdatamodeld from the ABC project folder into the XYZ project folder, and copy the associated populated MyDatabase.sqlite file from the simulator on project ABC into the simulator on project XYZ.
This does NOT work.
I get the error "The model used to open the store is incompatible with the one used to create the store"
I've tried resetting simulator, deleting all apps from simulator, running CLEAN in XCode, and still doesn't work.
When I run XYZ, it WILL create a new EMPTY sqlite database, but it will NOT accept my populated one that is associated with the ABC project and which works fine in ABC.
I need to be able to use my populated one.
The error message tells the tale. You have changed the xcdatamodeld between the time you wrote MyDatabase.sqlite and now. Core Data needs the original xcdatamodeld (unchanged) to be able to read your datafile. Retrieve it from your version control system or from Time Machine and you'll be good to go, although you might have to handle model migration.
I have an app in the app store that uses Core Data and I have to release an update by tomorrow. However, I am experiencing some problems with Core Data.I by mistake made changes to my model in Core Data and now my app is crashing. I tried migrating the data but the app still crashes when I updated it on my iPhone. Is there anyway to fix it?
Thank you so much for your help!
EDIT: I am trying to add the .mom file to the app but I can not get it into the Bundle:
EDIT 2: Do I delete the entirely Planner.xcdatamodeld:
You can recover the original Core Data model from the production app's bundle.
Use Finder to open the app bundle (Show Package Contents) and look for a .mom file or a .momd directory.
Copy the file or directory to some location outside the bundle.
Create a new XCode project with Core Data.
In XCode select the newly created projects Core Data model.
Go to the XCode Editor -> Import menu and select the .mom file you have just copied, if need be find the correct version in the .momd directory.
You should now have the model in XCode, save and copy the model file to you original project...
In XCode delete the incorrect model from your project (remember to save a copy first so you have a copy of the new changes)
Use the XCode Add File to... menu to add the old model to the original project
Now compile and run the app to confirm it opens the old file correctly
Now add a new model version and add the changes to this new version - make sure you select the new model version in XCode before making changes
You should revert your model to the one that you have in App Store. Then you should Add new model version of your Core Data model. If you can't revert to that model you should try to make it exactly as it was.
After you've done a new model version, you should select that one and make the changes.
If you don't use Git (which is really, really bad, by the way), you can just install your app from the App Store and use some iPhone File Manager to get the old mom file from your app. It would be in /apps/yorapp/youapp.app/ folder with .mom extension
Try iExplorer, for example, it's free.
I'm toying a lot with core data lately, and what bugs me is that you create a .xcdatamodeld to create your base structure, but then xcode convert it in a .momd file
My question is this : is it possible to do the conversion programmatically, instead of having it done by xcode?
Let's say for instance we wan't to be able to download a xcdatamodeld file from internet in an iOS app, and have it interpret it and create the underlying base.
You can create a momd file starting from an xcdatamodeld source using the momc script from Apple.
An xcdatamodeld “source” directory is compiled into a momd deployment directory, and an xcdatamodel “source” file is compiled into a mom deployment file.
(As explained here https://developer.apple.com/library/mac/documentation/cocoa/conceptual/coredata/articles/cdUsingMOM.html)
How to use the script:
Make a copy of the xcdatamodeld file you want to transform. It will be replaced.
Open the terminal and go to the Developer bin folder
cd /Applications/Xcode.app/Contents/Developer/usr/bin/
Run the momc script on your xcdatamodeld file
Usage: momc source destination
Example (it's important to put extensions):
./momc input.xcdatamodeld result.momd
If you download the entire xcdatamodeld bundle (it's a directory) and unpack it, you can use code from my momcom project to compile it into a .momd. You could then load that like any other data model. This project is still somewhat experimental, but it's performed well in testing so far. [Update: the project won't work on iOS as it is, because it uses NSXMLDocument. If you wanted to try this, you could use TouchXML, which is designed to be a drop-in replacement for NSXMLDocument. I don't know of any other options for compiling a Core Data model in your own app.]
The usual rules about having a data model and a persistent store match up apply. You couldn't just take the newly compiled model and use it with an existing store unless you handled model migration. Also, I have no idea what Apple's attitude would be regarding an app that downloaded new data model files-- it might be fine, or it might get you into some trouble with them.
No you can't download a xcdatamodeld file from internet and put it working. If you do so your programme will crash because of wrong data model. your data model needs to be in the main bundle and you have to select current data model. Core data maintain model version and some information about your data model. Even if you change your model and do not migrate the model your programme will crash and you have to delete the application from your device/simulator.
However, you can download the .sqlite database but data model should be the same.
I've created a versioned Core Data model in my iOS app, and it has several versions created so far (several .xdatamodel files within the .xcdatamodeld bundle). Before shipping the app, I'm considering deleting these old versions so I can start with a single clean data model - and data loss isn't an issue at this stage.
Is this possible? And what would be the best way to achieve this without simply deleting all Core data files and recreating a new model.
Deleting the old models means you cannot migrate any existing data stores. I assume you're ok with that given your statement about data loss. If you want to start fresh, you can take the current xcdatamodel, copy it somewhere else (e.g. your Desktop), then delete the xcdatamodeld folder. At this point, you can drag your saved xcdatamodel back into Xcode and re-add it as a non-versioned file.
If you want to get rid of old versions of the data model
(Note: make sure you copy the Data model file and save it somewhere in case something goes wrong)
Five Step solution
Select .xcdatamodeld file in Xcode, make sure you have the latest
version is set as the current data model.
Right, Click Show in finder if you don't see all your versions right
click again and show package contents.
Delete all the version except the latest.
Jump back to Xcode and now delete the .xcdatamodeld file just remove
reference don't move to trash.
Add the file back again
Voila it's done