iOS - populating a core data database - iphone

I have used extensively core data in my applications. Generally I need to submit the applications using a pre-populated database.
I generally create zillions of lines of code to populate the database, then I extract it from the applications directory and include it on the bundle. Is there a easy way to do that? Is there any way to populate a core data database created on Xcode using, for example, a CSV file and an external app?
thanks.

The usual way is to create the entries at the first launch.
If you want to import data from a CSV file, then you need a parser.
I can recommend this one: https://github.com/davedelong/CHCSVParser

You don't have any easy way to do that with Xcode.
Basically what I do in this kind of case: I build a second target dedicate to pool the database and create object with a fixed persistent store url relative to the workspace in the filesystem.

Related

Creating .sqlite file from Core Data store?

I've seen tutorials in books and on websites that offer .sqlite files for download. The sqlite files are used for Core Data.
How do I get a .sqlite file FROM an app or core data store on TO my desktop?
If you are going to create a pre-populated sqlite file to be used with Core Data then you must create it with Core Data. It is trivial to create a basic desktop application for data entry and use that to create the file and then embed it in your iOS device.
Do not attempt to duplicate the data structure or linkage within the file by hand. You might get it to work but you will spend way more time trying to get it to work and it is going to eventually fail. The internal structure of a Core Data sqlite file should be considered like a private API. The structure is not public and can change without notice.
If you are specifically trying to create a Core Data store, you use this method:
NSPersistentStoreCoordinator
addPersistentStoreWithType:(NSString*)storeType
configuration:(NSString*)configuration
URL:(NSString*)storeURL
options:(NSDictionary*)options
error:(NSError**)error
You must have already associated a NSManagedObjectModel with your persistent store coordinator object. If the store at storeURL does not exist, it will be created; otherwise it will be opened.
These might help: http://www.sqlite.org/cvstrac/wiki?p=ManagementTools
I like to use this Firefox plugin:
https://addons.mozilla.org/en-US/firefox/addon/5817/
You can create a new .sqlite file, change existing databases, and browse through your data.
There's a command line program download-able from sqlite.org (in the standard download) that can be used to create a blank database with a schema. Usually the database file is compatible across operating systems and devices.

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.

Deploying App With Dummy/Initial Data

I have a Core Data based application that stores hierarchal data displayed using a series of UITableViews. To illustrate my app functionality to the user I would like to pre-populate my database/app with some dummy values. This data would be available upon installation on the user's iPhone/iPod Touch.
What is the best way to achieve this?
Create the data and include it in the app bundle. On first launch, copy that sqlite file to the documents directory and then stand up the core data stack afterwards.
Personally i would create a desktop app using the same model to do the initial data entry to make it easier on you. From there take the sqlite file that is generated and include it in your appilcation.

Is there a good application for managing a SQLite 3 database with BLOB data type?

I want to create and manage a database with images and or audio clips. I know it's not the best idea and I know there are better options, but it's the easiest way to have the data separate from the programming and I'm not the one writing the code. So I need an application that will allow me to edit the database that the application is calling, and the application needs to call random audio or image file. I JUST NEED TO KNOW OF AN SQL EDITOR.
Super bad idea to put large files in a database, it will kill performance and could well blow away the memory limits an application has. You also cannot stream them out of the database the way you can from the file system.
Instead, consider this approach - as Alex suggested, work with separate files and strings that represent file names. You could put both the database and the files into a single directory, that your coder keeps as a folder reference in XCode - so all content in the folder you change is added to the coding project automatically. Note that if you change any existing file, due to a bug in XCode he'll be required to do a Clean BUild before building again or it will not copy changed assets (mostly a problem for the DB).
Then you can easily use any SQLLite client to maintain the database of filenames and other data. "Base" is a nice standalone app.
I would highly recommend you use some source control system like Git so that you could check in changes and the programmer could get his project updated right away without the confusion of emailing files around.
You could use Core Data instead. It uses a SQLite backend, by default. Instead of using BLOBs, you can simply store an NSString* that is a path to the object in the application's Documents folder. When you want to retrieve a stored image or other large binary data object, you can load an NSData* instance from the path value directly. Keeping large files outside the database will give you much better performance.

How do I initialize a store with default data in a CoreData application?

I'm doing an iPhone application. In this app, I just want to have a database to be used as a looked up table for values in my app. The only thing the database will do was to supply me the values I needed depending on the query of the program. It won't do any addition or deletion in the database. My question was how do I initialize a default data on the application using CoreData. So that when the program starts It already had all the values needed.
If you have other suggestions of what is better do or what are other alternatives, please tell me.
Thanks.
I would create a simple Mac application, starting from the template for a Core Data document-based application. Copy your existing .xcdatamodel over the default one in the project (or add the new data model and be sure to rename anywhere that refers to the default model). Open up the XIB file for the document window in Interface Builder and drag the Core Data Entity item into it from the Interface Builder library inspector. From the resulting dialog, choose an entity to display and select an interface to display it in.
What this will do is create a fully functional interface for adding, removing, or editing the properties of that entity type. Everything should be hooked up via Cocoa Bindings so that you don't need to write a line of code for this to work. You can add interfaces for each entity type in your model this way.
This will let you quickly enter and edit data within a Core Data document, which you can then save out to disk and add as a resource to your iPhone application. The SQLite database structures are fully compatible between the desktop and iPhone Core Data implementations, so I've found that this is a quick and easy way of testing your iPhone Core Data code.
Please refer to the Core Data Programming Guide, or see below (copy from the PG):
"
How do I initialize a store with default data?
There are two issues here: creating the data, and ensuring the data is imported only once.
There are several ways to create the data.
You can create a separate persistent store that contains the default
data and include the store as an application resource. When you want
to use it, you must either copy the whole store to a suitable
location, or copy the objects from the defaults store to an existing
store. For small datasets, you can create the managed objects
directly in code.
You can create a property list—or some other file-based
representation—of the data, and store it as an application resource.
When you want to use it, you must open the file and parse the
representation to create managed objects.
You should not use this technique on iOS, and only if absolutely necessary on Mac OS X. Parsing a file to create a store incurs unnecessary overhead. It is much better to create a Core Data store yourself offline and use it directly in your application.
There are also several ways to ensure that the defaults are imported only once:
If you are using iOS or creating a non-document-based application for
Mac OS X, you can add a check on application launch to determine
whether a file exists at the location you specify for the
application’s store. If it doesn't, you need to import the data. For
an iOS-based example, see CoreDataBooks .
If you are creating a document-based application using NSPersistentDocument, you initialize
the defaults in initWithType:error:.
If there is a possibility that the store (hence file) might be
created but the data not imported, then you can add a metadata flag
to the store. You can check the metadata (using
metadataForPersistentStoreWithURL:error:) more efficiently than
executing a fetch (and it does not require you to hard code any
default data values).
"
As mentioned above, generally we need to create a pre-populated default store with code, then use it as a
resource file, and copy it from resource bundle to document directory if the coredata file is missing. Please search the CoreDataBooks code example in your Xcode Organizer (or Apple Developer Center), and look at the - (NSPersistentStoreCoordinator *)persistentStoreCoordinator method.
I racked my brain for hours attempting to solve this. What I came up with was simply not to save the database. That way, it will be initialized each time the app is opened. If you save it, it will continue to duplicate.
I would write a tool that populates a database with the data you want in it, generate the db at build time and stuff it in your resources folder. If you are not going to write to it you can just leave it there and access it directly, if you ever did want to write to it you would need to copy it somewhere you are allowed to write (like the documents folder).