core-data update in live app - iphone

Hoping to get some clear advice on this one.
I want to push updates to my app when it is live. I plan to do this by modifying the sqlite that ships with the app and then have the app download it. Easy.
I haven't worked out how actually get the app to see the new data though.. I can overwrite the sqlite in the documents directory, but the app has to be restarted for the new data to be picked up - no good. As a first step I don't mind if modifications to it are lost, but I am really looking for a way to keep any modifications to data, and add/remove entries based on the new sqlite. It will be the entire data-set rather than just the changes.
I am going down this path as the data is quite complex, but manageable through a desktop app based on same core-data model.
Is there a common way, or a way at all to achieve this?
Thanks.

There is no simple way to completely merge to two Core Data stores SQL or other wise.
Maintaining the integrity of the object graph requires that new data be inserted into the existing store via a context using the same model as that used to create the store. In other words, batch adding new data to the store is the same logical process as adding it one piece at a time from UI. You insert NSManagedObject instances, populate them, set their relationships and save them.
In theory, you could write great gobs of code to merge the old and new SQL databases into a new SQL store that Core Data could read. However, that is complex, unsupported and likely to break when Apple revs something in the future.
I would recommend having the app itself download the data piecemeal from the server and then insert the new data into the existing store. It's trivial to send data using something like JSON. Alternatively, you could download a new store, add it to the existing persistent store coordinator and then create clones the new objects in the old store. Then remove the downloaded store from the coordinator and delete the downloaded store file.

Related

Start over and upgrade the app that is in the store (New project - CoreData)

I have one app in the store with CoreData model, and i want change entirely the app (remove some garbage, organize, new CoreData model... etc).
So i thinking start over and create new project, what will happen when i try to upgrade the old app that is in the store to this new one? (i'm concerned about CoreData)
thanks a lot
If you change a core data model even slightly, you need to migrate data to the new model:
You can only open a Core Data store using the managed object model used to create it. Changing a model will therefore make it incompatible with (and so unable to open) the stores it previously created. If you change your model, you therefore need to change the data in existing stores to new version—changing the store format is known as migration.
That's from Apple's docs: http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreDataVersioning/Articles/Introduction.html
So if you want users to have their old data in your new version you're essentially going to have to replicate the old core data model in order to extract and migrate the data to your new model. For any release subsequent to that one, of course, you can get rid of the old model.

Pre-populated database. Now I want to add more data without messing the pre-existing data

I have set up and app which has pre-populated data that copies the database to the project's store. Using the 'CoreDataBooks example' method:
Any way to pre populate core data?
For application upgrades, I want to add more data to the database but I don't want to change the existing database since new user data is stored there?
What's the best way to do this?
I'm thinking I would create a new versioned managed object model (I'm not sure if you can add a new MOM version if nothing in the schema actually changes), for new versions, read the currently running MOM version, migrate the MOM to the latest version and manually add the new records in the code that have not been added since the currently running MOM version.
It seems a bit tedious to manually add new records in the code. Does that sound right or is there a more elegant way to add this new data?
Thanks!
If you change the managed object model itself e.g. add a new entity or change an existing attribute, then you need to use migration to update the existing persistent store. See the Core Data docs for details on migration.
If you just want to add new data, then you don't have any choice but to do so "manually."
Remember, Core Data is an object graph management system, not a database. An object "graph" is a "web" of interrelated objects so the only way to add data to the graph is to create new objects and set their relationships. It's not inefficient, it just the way it works.

Is it better to create persistent stores, or use fixed files for data?

I'm prototyping a simple sports sim game for iPhone which will use Core data.
One the biggest challenges I'm facing is how to get the data into Core data in the first place.
The second biggest challenge is whether I should use core data's persistent stores or use fixed files (JSON) for pre-fixed game data.
--
Concept
The general concept is that a player can start a new game or continue an existing one.
When they start new game they would use pre-fixed data. (IE. A database which is read-only.)
When they continue game they would use a different database (the game database).
I am not sure how to deliver such a feature.
--
Prototype
Currently, I am experimenting with this prototype:
PHP Web App -> 2. API -> 3. iPhone
A local PHP web app which acts as a CMS.
A basic API which lets me expose specific data in a JSON format.
Read the JSON into Core Data using TouchJSON/other tools.
I have no intention of making the API public/online (for various reasons), so the method I have described is a only meant to ever be a one-way process.
This will of course cause a problem because I need to make the data read-only.
--
In sports sim games you will often find them using fixed files (.txt, .csv, .dat, etc) and then they read this data into memory or a database.
Therefore, using this concept I could:
Save the JSON as fixed files and read them at run-time into memory/core data.
And then whenever the player starts a new game, the existing core data store will simply be wiped.
However, having said that I've heard that you can use persistent stores as a method to overcome this problem.
Therefore I was thinking of setting up 2 persistent stores;
1) A pre-fixed read-only persistent store
2) The actual game store (which gets overwritten if you start a new game).
But which is better?
Creating JSON fixed files for consumption, or using 2 persistent stores?
I apologize if my question/concept is overly complex; but would welcome better/simpler solutions where possible.
I think you can use Core Data for applications that is going to store data on it and the database is empty when it starts but if you needed you data store to be pre-populated with data it is better to load it from fixed data like sqlite or xml files.

Preserving core data after app update

I am using core data to store favorites chosen by the user. I would like to know that if I send an app update, how can I keep the data of the favorites preserved after the app is updated by the user?
I have read that you could use versioning, but I'm not sure if this the correct method.
Any help will be appreciated! Thanks
If your app maintains the same bundle identifier and you don't copy over the core data store file, you keep it.
If you changed your Core Data model, then you do need to worry about versioning. Depending on changes you may need to write rules for migrating data in the old store to the new format. As you have probably experienced, if you change data structure and do not migrate (or wipe existing data), you crash.

How to have multiple apps - one Core Data?

I’m an experienced developer, but new to Mac. I just don’t want to go down one path only to find out that I made some fundamental error or incorrect assumption later on.
I want to ultimately build and sell an iPhone app using Core Data. The app will be free with content available through in-app purchase. Here is what I want to be able to do:
OPTION 1
Build a Mac OS X utility app that points to the same Core Data object model, but has its own “master” database.
Populate the master database using the Mac app.
Export a subset of the master data from the Mac app to a flat file (XML?) that is a subset of the master data.
When the user purchases that data, download from the cloud and import that data into the local iPhone data store.
Number 2 should be easy enough. I have read about the XML Parser that should help me with #4. I need help with #1 and 3.
For #1, I can’t figure out how I can maintain one object model for both apps with Xcode. That data model must accept model versioning. Do I just create two Projects, one Mac and one iPhone, and point them both to the same .xcdatamodel file and the magic happens for me?
For #3, is there any sample code that someone can share that will iterate through an array of objects to create the XML?
OPTION 2
Another option I am considering was discussed below. Instead of worrying about import/export, simply create individual sql files for each set of new or updated data.
I could maintain a separate "metadata" database that has information about the individual sql files that are available to the app.
Then, I can dynamically access the individual SQL files from the local documents directory. This is similar to an iBooks model where the sql files equate to individual books.
I'm thinking I could have only two active database connections at a time... one for the metadata and the other for the specific "book". I am not sure if this will scale to many (tens or hundreds) sql files, however.
Any help is appreciated!
Jon
UPDATE: I just saw the answer from Marcus Zarra at:
Removing and adding persistent stores to a core data application
It sounds like Option 2 is a bad idea.
For (1), you can use the same object model in both apps. Indeed, if you use the same Core Data generated store, you are required to do so. Simply, include the same model file in both apps. In Xcode, the easiest way to do this is to put the model file external to the project folders of each project and then add the model file without copying it to the project folder. This will ensure that both apps use the same model file for every build.
For (3), you need to first create an "export" persistent store using the same model as the reference store and add it to the reference context. In the model, create an "Export" configuration. Create a subentity for every entity in the model but do not change any attributes or relationships. Assign those entities to the Export configuration.
You will need to add a "Clone" method to each ManagedObject subclass for the reference entities. When triggered, the method will return a subentity populated with the reference objects attributes and relationships (the relationship objects will be cloned as well.)
Be aware that cloning an object graph is recursive and can use a lot of memory.
When you save, because you assigned them to the "Export" configuration, all the cloned export entities and their relationships will be saved to the export store. You will have cloned not only the objects but the related object graph.
Include the model and the export store in the iPhone app. Write the app to make use of the export entities only. It will never notice the absence of any reference objects.
For (4), I wouldn't mess around with using XML or exporting the data outside of core data at all. I would just use the export Core Data SQL store created in (3) and be done with it.
You can give a NSManagedObjectContext instance and instance of NSPersistentStoreCoordinator. This class has options allowing you to specify a file location for sotring data and a format (SQLite, Binary, or XML)
How do you plan to actually transfer data from Mac to iPhone? Is this something you do during development, or something people do during daily use? If the latter, you are probably better off building decoupled export/import into your app right away. So the Mac would serialize data into XML or JSON, push it somewhere in the cloud (not sure if local network/bonjour transfer is easier or useful, cloud is more universal), and iPhone fetches the data and deserializes it into the local schema/repository. You should not plan to work on the SQL layer with Core Data. Different platforms may use a different storage backend.