My app involves getting a large json file via the internet, and then parsing it into Core Data.
Thats fine, but how could I get the already filled version of this Core Data database into my app, so it is there when they first launch it. And the user can decide to refresh it later.
There's a reasonable tutorial about pre-loading over at Ray Wenderlich's site.
Generally - create a separate project, parse the JSON file into a core data database. Create your real project, copy the Object model and the database file to this new project.
Now, at app start up, check if the database exists in the document's directory, and if it does not, copy your prefilled one from your app bundle.
Make sure that the Persistent Store Coordinator works with the database in the documents folder and not the one in the app bundle.
Update June 2012
I've got a small example project on GitHub called PromNight which demonstrates using an Xcode Workspace with an iPad project and a OS X project to preload the data for Core Data. This uses an object model that is shared between the the two applications which helps to keep changes in sync when preloading.
Core Data uses a backing store, which is essentially a sqlite database (or, on Mac OS, optionally an XML file). You should simply add that file to your app's bundle and ship it with the app. As far as getting the data into the database, here's what I would do:
Write some code to import the data from whatever format you have it in.
Run that code.
Copy the sqlite file off of the device or from the simulator.
Add the newly created sqlite file to your project in Xcode.
I wouldn't hand-create the sqlite file, since Core Data does some "voodoo" behind the scenes and messing with the sqlite can break things. Also, I've seen developers use multiple targets. for the import. This way, they can write the code in a compiler conditional and then not have to worry as much about project maintenance. For example:
#ifdef kImportTarget
//run core data import
#else
// run the Core Data stack setup from an existing file
#endif
The Core Data database is just a SQLite database file. You can deliver it in your main bundle and then copy it to your documents folder before associating it with your persistent store coordinator.
Related
I have read that this works, but I can't get it to. I want to pre populate Core Data. I ran my project so it would create the sqlite file. I copied that to my desktop and then prepopulated it using the command line, sqlite3. I ran queries to make sure it was populated correctly. So now I re-add it to my project. No matter what I do, though, it won't fetch the data.
I got it to work ONCE. I re-copied the sqlite file from my project's document folder after running it in the simulator. I then populated this new sqlite file. I put it back in my project and I got the contents to display.
I think the problem is the Z_METADATA table. This table has a Z_UUID attribute. I think the only time it worked was when the simulator's UUID and the sqlite's Z_UUID attribute were the same.
I went into ~/Library/Developer/Xcode/DerivedData and deleted the contents of the DerivedData folder. So now my simulator will have a different UUID when I run it. I did this and now the contents of the sqlite file will not display. This is why I think the Z_METADATA table is the problem. The Z_METADATA's UUID and my simulator's UUID are not the same so for some reason it can't use it?
All the articles about pre populating Core Data this way I found are old, around 2009, so I don't think this was a problem then. So can I use this method of copying the sqlite file, using the command line to pre populate it, then re-adding it to the project? Does anyone have a current way to prepopulate Core Data?
So the error is that my NSFetchedResultsController is returning a count of 0 objects. I got it to return all the data the one time I mentioned above.
According to the Core Data Programming Guide,
Important Although Core Data supports SQLite as a store type, the store format—like those of the other native Core Data stores—is private. You cannot create a SQLite database using native SQLite API and use it directly with Core Data (nor should you manipulate an existing Core Data SQLite store using native SQLite API). If you have an existing SQLite database, you need to import it into a Core Data store (see “Efficiently Importing Data”).
While I'm sure someone has reverse-engineered the Core Data sqlite format, Apple does not provide any documentation, and it is likely to change across across major OS releases.
Write a command-line app that uses Core Data to do your import.
I want to input data into a sqlite database so that core data can read from the file but I was wandering if there's a way of populating the sqlite data via xcode or do I have to spend lots of money on an sql manager of some kind like RazorSQL to do it?
I suppose you could do the following:
Create a CoreData-based project that uses the same data-model that you're going to use for your project. To be clear, make it a Mac project and not an iPhone project. Make sure that the project is using an SQLite store, and not something like XML or binary.
In Interface Builder, add a built-in CoreData Entity editor to your view and configure it to hook up with your model (most of this should be automatic!). Then, build and run this application, and you should be able to add as much data as you like. When you are done, simply find out where the persistent store was kept (usually somewhere like ~/Library/Application Support/MyAppName/) and copy that file for later use.
Then, you should be able to use that .sqlite file in any app that is made to work with the same data model. Good luck, and let me know how it goes!
i am working on an application that displays read-only data i am shipping.
it is more of a book.
It is easy with SQLite but i am not satisfied with the performance and trying to use Core Data.
The issue is with pre-filling Core Data is that it is a hard process.
My question is:
Is it possible to build an assistant iphone application (for me to use) which uses the same data model for pre-filling.
and then take the populated .xcdatamodel file and use it in my original application?
I hope this makes sense :)
Adham
I believe what you're asking is whether you can create a CoreData database upfront and copy it to the iPhone. Is that correct?
This article will help. Here's a quote:
I thus suggest the following five-step process:
Create your data in a comma-separated file, typically placing each row of data (an entity) in a row of the file and separating different columns (its attributes) by commas.
Write a standalone program and copy in your .xcdatamodel file from your main project.
Write code in your new program that parses your comma-separated file and inserts the information into a Core Data persistent store that should be identical to the persistent store in your main project.
Run the program in the Simulator
Copy your data from the Simulator's documents directory into your actual project's bundle.
It's possible, I've done it. I made a desktop application to read from a CSV file using the code here:
http://www.mac-developer-network.com/columns/coredata/may2009/
I just had to alter the way the CSV part worked, and change the model.
I copied and pasted my model from the model builder into the iPhone model. (Clicked on the "grid" area, selected all, copied)
Then I took the sqlite database the desktop app produced (found it in Application Support, in the folder for this application) and put it into the resources folder
I made some code to copy the sqlite into the documents folder on the iPhone (if it wasn't already there) at startup, in the applicationDidLaunch method. It's possible that having it in the resources folder is no good. Even though you're using the database as read only, Core Data may want to write something to it. Not sure about this though..
I used the sqlite file in the documents folder in my Core Data set up.
The desktop and iPhone Core Data sqlite file seem to be exactly the same format. You can transfer one sqlite file to another application (iPhone to iPhone too) as long as they have the same data model. In another application, I used NSXMLParser to create the Core Data sqlite file, then transferred it to another app, both on iPhone using the Simulator.
Yeah, your data source can be whatever you want it to be. The other suggestions are good ones. Create a managed object model (.xcdatamodel) identical to what you want to use in your app. Read in the data from your file, create a new instance of your managed object and populate it from the file. Then save, and dive into the bundle in the iPhone Simulator and copy it over. This has the added bonus of being in exactly the format you need, with all the helpful metadata. Copy your object model and your managed object classes and you're good to go.
Note, though, if you really intend for it to be read-only, and you're using it at install, it will be installed in your finished app's bundle (under Applications/{SIGNATURE}/Myapp.app). If you intend to edit this database or allow a user to save to it, it's a better idea to copy it to the Applications/{SIGNATURE}/Documents directory where your user database lives.
I'm trying create 2 apps, one that builds a persistent store, and another one that consumes it.
So far I have built one app that uses CoreData to successfully build a database from an XML file. So this project contains the data model, the .h/.m files for the entities, etc.
I'm now trying to enable the second app to read that .sqlite file by copying the data model file, the .h/.m files related to the entities and the sqlite file to that project (via add existing).
The code executes but always fails to find any objects in the database.
Are there any restrictions or correct steps to take when trying to copy over these files?
The solution here is deceptively simple.
Just copy your .xcdatamodel file from one project to another and then when you run your app in the simulator for the first time it'll create a Documents folder for the app. Just drop your saved .sqlite or .binary files into the yourApp/Documents directory on the device.
You can find the simulator directory in "~user/Library/Application Support/iPhone Simulator".
You can also download, edit, and upload the myApp directory on a provisioned iPhone by dragging and dropping into and out of the Organizer. Look at the Applications list.
The iPhone doesn't support xml stores with core data, only sqlite or atomic (binary). The sqlite store is by far the better option for most applications since it doesn't all have to be loaded into memory at runtime.
Is this what you meant?
I think (not 100 percent sure) in your app plist, if you set your application bundle name to the same thing, they will share resources because the device will think they are the same application...
I don't think this is going to work the way that you want it to. On the iPhone, each application runs in its own "sandbox", and it's not really possible for one application to write files that another can read.
Is it really two different projects, or is it two targets in the same project? That would seem to make a lot more sense, and then you can share entity objects as they change.
For copying core data files from one project to another, I first created a new project with core data support and then I opened the contents of the previous coredata file and except the root tag, pasted all child tags in the new core data file in new project.
Previousy I tried to delete the coredata file in new project, copy pasted the previous one and changed its name and it was not working.
I'm working on a Core Data app (for iPhone 3.0, though I don't think that really makes a difference here) and it will need to ship with a "starter" database filled with data. With SQLite, I would just have the App copy the populated database from the bundle into the App's documents directory on first launch and then load that database - all the information would come along with it and we'd be ready to go. But with Core Data, I'm not really sure if I can just save the Persistent store to the App bundle and copy it before having Core Data start doing its thing. Will this cause any problems? There is quite a bit of initial data, so I don't want to package it in another format and have to parse through it.
Yes, you can copy over a pre-populated persistent store.
I created a Mac app that populates a store. It is copied into my bundle and at start, copied to the Docs directory. This works fine. I am told the Core Data Books example was developed the same way.
Please note this doesn't mean you can just copy over any old SQLite file. It has to be a Core Data persistent store, though I think you understand that based on your question.
Actually there is a trick: you must name the file you are going to copy over with an extension other than ".sqlite", ".bin" will do. Otherwise Xcode will change the contents of the file when it copies it into the app during the build phase and it won't load.