Is it possible to generate a Core Data structure programmatically? - iphone

I am currently working on a project which may require the ability to generate a Core Data model and classes automatically from a JSON feed which describes each object, it's properties and relationships. This would enable our company to quickly generate a working core data database from our CRM at the start of each project.
Is this possible/easy to achieve? If so, does anyone have any tips on where I can get started?
I have already created various iOS apps which use Core Data but I have never made one which needs to automatically create a Core Data model.

Yes, you can create a Core Data model dynamically. An NSManagedObjectModel can be created without a stored model, and NSEntityDescription/NSAttributeDescription instances can be defined and added to it before being passed to an NSPersistentStoreCoordinator. Apple has an example of doing this in their Core Data Utility Tutorial.

Related

iOS Core Data: Confused about Core Data and database

I am really confused on what the Core Data actually is. Or I guess my question is, when dealing with a database, would you use Core Data? Like if I wanted access values from a database would I be using Core Data to access those values? How would I approach this problem?
Thank you so much for the help.
Core Data is an framework that does the work of "object persistence". In other words, it's code you can use that takes care of saving a collection of objects to disk and loading them again later. It does a lot of work to allow you to store lots of data and load only the objects you need at a time, and unload ones when memory is tight.
Core Data can use a database to accomplish this, but that's it's business, not yours. When you use Core Data, it is a black box. You tell it to save the data and then step out of the way.
If you want to interact with an existing database, such as a MySQL database on a web server, that's a completely different matter. You might use Core Data to store local copies of objects on your device, but in that case Core Data won't care that the objects are copies from some other database. It doesn't care.
It is a convenient, native means of storing data in your iOS applications. Don't think of it as sqlite although you can view the files it creates with various sqlite tools. Instead think of it as a tool for manipulating an object graph of information important to your app.
I've used it in two main ways. First to store a bunch of static data that is important to an app, in one case that was a large amount of location data for an indoor mapping application. What arrived as a massive CSV file of waypoints was converted to core data. Core Data was incredibly useful for this because it allowed preparing a sqlite file which was shipped with the application containing all the infomation. Updates from a web service arrive as more CSV that is added to the Core Data to keep information current. At runtime the location information object (the waypoint a user is at) is retrieved with a predicate (i.e. the point they tapped on) and that object, through its Core Data relationships, indicates where it is possible to go from that point. Core Data provided the information necessary to perform A* routing through the indoor map.
Second it is great when you have a bunch of objects arriving as JSON and you want to be able to store and access those objects later. Let's say you have a typical app where you have a User and some information about the User, let's call it Thing. Users have Things. When you want to know something about a User you retrieve the Core Data record using a predicate - typically "name" or similar - and you get all the information you stored about the User back. Again you can make use of relationships to explore the user's connections and make displaying information easy. Perhaps the User has many Things, then you can say "user.things" and you get a NSSet of NSManagedObjects representing those Things.
You use it like a database. Its utility is that it is easy to access from anywhere in your iOS code, it is easy to store and easy to retrieve information also. Faulting lets you retrieve one object and navigate to any object connected through relationships by following the relationships. Because you define the attributes and relationships yourself in the data model editor it is easily customized for what you need to store. To me it is one of the most used and most useful parts of iOS.
When you want to automate display of information from Core Data you can use a NSFetchedResultsController to initiate a fetch and to respond through delegate methods to changes to the underlying data. If you set up a UITableView to use a NSFetchedResultsController as data source, you can have the table automatically update whenever the objects displayed in the cells changed. Very useful for apps where you periodically update information and want what is displayed to be kept current.
When your object model changes it is possible to maintain all of your existing information and migrate it to the new model. Core Data manages automatic (lightweight migration) when it can, or if you have made more radical changes you can supply rules to handle the migration.
The limitation of Core Data is that it is not great for storing binaries. If you have images that you need to store, far better to store a path to the location of the image than trying to store the actual data.
Yes, if you want a local database on your device, Core Data is the appropriate technology. It probably makes sense to start your research with the Core Data Programming Guide.
You can alternatively use SQLite (which Core Data uses in the backend), but Core Data offers some material advantages and is the preferred database interface for iOS. If you decide to pursue SQLite for any reason, though, I'd suggest you contemplate using the FMDB Objective-C SQLite wrapper.
But Core Data is generally the way to go.

How should I migrate my core data?

My core data store in the previous version to my app is different to the current one in the following ways:
Attributes missing
New attributes
Attributes which need changing
New entities
New relationships
Attributes which need moving between entities
How should I go about migrating my data? What I had in mind before looking into this was that I could just write code that could take the data from the previous model and put it in place in the new model.
I think the Core Data Model Versioning and Data Migration Programming Guide will cover these issues in some detail.

Core data versioning and migration

I have the older version of the core data model of the released app. Now, in the next version of the app, I am migrating the core data model to new model. Is there a way to get the attribute values from the old model before actually migrating to the new version of the model or is there possibly a way to know if the migration is to be occurred.
When you migrate, Core Data actually moves existing values for you. If you're doing a relatively simple migration, such as adding or removing some properties, Core Data does its best to make the move as seamless as possible. In many cases, you won't need to make any changes other than set your new model. See my answer here for more.
Yes, it is possible.
To get the attribute values from the old model you'll need to create custom entity migration policies (NSEntityMigrationPolicy subclasses). Then in -createDestinationInstancesForSourceInstance:entityMapping:manager:error: you'll receive source instance, and it is completely up to you how to create destination instances from source instances.
There is a method to check if a given store is compatible with store coordinator model: -[NSManagedObjectModel isConfiguration:compatibleWithStoreMetadata:].

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.

New to Core Data for iphone

I am new to the iphone platform and am creating an app that retrievals a rss feed and displays it in a UITableView. I have gotten this working perfectly (or rather, the way I wanted). What I was thinking was I would store the current feed items on the phone so that it would initally load the old items it has stored while it got the new feed, then parse the new feed and add the new items and refresh the TableView. I was going to use Core Data to store it the old feed items because it would be a good way of learning Core Data and it would be an appropriate use of Core Data. However, I am having a difficult time learning how to use Core Data and connecting it with the Table/Array.
I have already googled and looked on stackoverflow for tutorials but have yet to find anything that explains it in a way I really understand. Any explanation of the overall steps that it takes to add Core Data to an existing app would be greatly appreciated. Full-blown detail are not necessary (but would also be useful). I'm just not very experienced with SQL or storing of data in such a manner and am having trouble wrapping my head around how the whole concept of Core Data works and how it connects to everything.
Also, any better method of doing what I'm trying to accomplish would also be appreciated.
There exist Xcode templates for Core Data-based applications; these are a great start to getting Core Data off the ground. However, it sounds like you want to integrate Core Data into your existing app, so you'll need to...
Add three main Core Data objects: the managed object context (MOC), the managed object model (MOM), and the persistent store coordinator (PSC). These need to be accessible wherever you want Core Data available, so either in your app delegate or, more preferably, in the controller or data source for your table view.
Create a MOM in Xcode. This will be a file of type .xcdatamodel, and it's an object graph that defines all the Core Data entities you want in your app.
Use NSFetchedResultsController (as suggested by Louis Gerbarg) to get data out of Core Data and display it into your table view.
Add code in your existing RSS-fetching-and-parsing routines to store new Core Data objects back into the store, when appropriate.
A good way to start is just to create a new Core Data application and play around with it a bit; you can also look at Apple's fantastic resources on the subject, like the Core Data Programming Guide and the sample apps Recipes and Locations. (Developer registration may be required.)
One last thing to note is that for the most part, a lot of the Core Data code you need to add can be ripped straight out of one of the Xcode template apps and pasted into your program (this holds especially true for the accessors for the three Core Data objects you need). Be careful not to use code you don't understand, though.
If you are using CoreData to populate a UITableView you really want to use NSFetchedResultsController as opposed to trying to populate and sync array yourself. The documentation for NSFetchedResultsController includes links to several CoreData tutorials, including onces that populate table views.
NSFetchedResultsController is still a bit buggy and requires fragile workarounds. I would start with the simpler iPhone Core Data "location" tutorial before moving on to the Books tutorial.
Also, any better method of doing what I'm trying to accomplish would also be appreciate
yes, it sounds like Core Data might be overkill for your application. Assuming your feed items are stored in a collection object you can easily use OSX's built in serializaition.
Been noted in other Stack-Overflow posts, but I can highly recommend the Prag Prog book "Core Data: Apple's API for Persisting Data on Mac OS X" - most is also relevant to iPhone Core Data apps; there is a whole chapter on creating an iPhone app too.
http://pragprog.com/titles/mzcd/core-data