views:

112

answers:

3

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

  1. Build a Mac OS X utility app that points to the same Core Data object model, but has its own “master” database.
  2. Populate the master database using the Mac app.
  3. Export a subset of the master data from the Mac app to a flat file (XML?) that is a subset of the master data.
  4. 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:

http://stackoverflow.com/questions/2257557/removing-and-adding-persistent-stores-to-a-core-data-application

It sounds like Option 2 is a bad idea.

A: 

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)

Maz
Thanks, Maz. So far, I'm leaning toward TechZen's solution. I just don't know if it is feasible to have a large number of individual sql files on the iPhone.
jschmidt
+1  A: 

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.

TechZen
Thanks for the suggestions! The reason I want to use #4 is that I want to sell multiple sets of data as individual in-app purchase products (tens or hundreds).It seems to me that it is not efficient to have that many individual sql files, but perhaps I'm wrong.One possibility:-Master database that contains meta data about the purchased database products. Two data models, correct?-When a specific product is requested by user, open connection to that sql file-Display the results to the user.Essentially, this is a "book reader" app except instead of books, it is formatted data.
jschmidt
With this method, I could even eliminate #3 because with the Mac app, I will just create individual sql files instead of one master database to export from. The more I think about this, the more I like it. Is it feasible to have dozens of sql files available to open on the iPhone?
jschmidt
You can have multiple stores, multiple models and multiple context active at once in almost any combination. As well you can dynamically add and remove stores. The only real limitation is that you can't create relationships between objects persisted in separate stores (although you can have fetched relationships.) I would just save everything as SQL stores and then add them to the master context as needed. As long as they all use the same model, there won't be problem.
TechZen
If you're going to include all the content within the app download, you might as well use one big store and avoid the complexity of multiple stores. If you're going to download content you can either download the store file or just write the data directly into the master store.
TechZen
Thanks again. I can't ship the app with content because content will be added and changed too often and I don't want to have to go through app approval process every time. So, content must be loaded. I guess what I'm struggling with is: is it better to have 100 stores each with same model or one store and take time to import? You seem to indicate that you can have multiple stores with the same model added to the context all at the same time? Is that a lot of overhead/memory? Do I need to release unused stores or does Core Data manage that for me?
jschmidt
If you use the same model for every store (which is likely) then I'm pretty sure you can add and remove read only stores on the fly. At the very least, you cold always activate another Core Data stack for the new store. I don't think an import would take any longer than downloading the file itself so I would lean towards a single store in order to reduce complexity. Memory use is not dependent on the size of the store/s but instead on the number of objects alive in memory at any given time.
TechZen
You might should look at the Mac side, Core Data Document architecture. It's more of what you want than a unitary database. It used to allow core data to store things like word processing documents. Each document is its own store. An ebook like model would be like that than a database per se.
TechZen
A: 

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.

Jaanus
The data will be downloaded from the cloud as an in-app purchase. There will be updates to existing data as well as purchases of new sets of data. Existing data is not expected to change often, but users can purchase new sets of data at any time. About decoupled import/export, that's what I was thinking originally. What do you think about multiple SQL files, though? That would avoid the need to import/export from the database altogether, but I would have to maintain multiple local sql files on the iPhone and dynamically connect upon user demand (similar to iBooks opening an individual book)
jschmidt
I don't like the idea of raw SQL for any of this because Core Data may or may not be using a SQL backend at any given time, and even if you use SQL on both sides, there is a lot of autogenerated magic in Core Data that you do not just want to mess with (e.g do all internal ID-s match in all devices? etc). I am sure you can if you are good at that, but why bother. SQL is just implementation detail of CD, and I think of it very differently from a regular SQL backend.
Jaanus
I agree. I will just use an import/export functionality. In fact, I just found in Marcus Zarra's book how to deal with that very issue!
jschmidt
Yep, Zarra is definitely an expert on the topic.
Jaanus