Why would someone using Core Data want to use more than one persistent store in the same Managed Object Model? - objective-c

I'm pretty new to Core Data, and I'm trying to wrap my head around it.

You might have cases where you want different types of data stored in different places or with different behaviors. For example you might have one read only sqlite store shipped as part of your app containing some default data, an additional store for updates to that data set you have downloaded from a server, and a third for user data. Alternately you might have a case where you want some objects to be persisted while others can live in an in-memory store and do not need to be saved between uses of the app.

Related

Add objects to core data only once

I want to create a large database. I am thinking of using core data for this purpose.But i want to insert the data to it manually and only once. This data is never deleted or edited but only read. How can i use core data to add such large number of objects to database? How to create database in core data and write only once.
Your question is quite general but I'll try to give you some hints on it.
Based on my experience, the simplest way to achieve it, it's to follow these two steps:
1) You could create an external file, in XML, JSON or plist format, that you can parse and use to create a prepulated a Core Data store. You can find some info in core-data-tutorial-how-to-preloadimport-existing-data-updated. In particular, you could set up a dummy project (or just use the AppDelegate methods) and use it to create the store, e.g. MyDataStore.sqlite.
2) Once you created, forget about the routines you have previously used and you ship the store in the application's bundle of your app. There the store is read-only. Otherwise, if you need to modify it, you are not allowed to do it and so you need to move it, for example, to the document directory.
You cand find additional info in the following SO topics:
Is Core Data useful for readonly data too?
How can I ship my app with a pre-populated Core Data database?
Core Data Store included in App Bundle
P.S. If you are in production and you need to make same change to your store, you need to republish the app (since the store is within the main bundle). To avoid this you need to move the store to a different directory and set up, for example, a sort of sync mechanism.
Hope that helps.

Way to Prepopulate Core Data with Certain Data

Usually I populate my core data with data from internet.
But say I want to prepopulate it with data without downloading it from internet.
Say I want to store all cities, or all tags first.
What would be the standard way to do so?
Should I store the cities on plist?
Should I hardcode inserting all data?
Should I set a variable in coredata to tell whether it has been initialized or not?
What do you guys do?
If it's a lot of data, the fastest way is to provide a populated store. Assuming you're using a sqlite database, you can simply use the Simulator to generate it once, and then put that in your app.
If it's a small amount of data, I'd insert the data at first start, while reading it from some form of xml, csv, or even hardcoded (script-generated) insert statements. It all depends on the situation.
When using Core Data not read-only, you should copy the database to a place where you're allowed to write, when the app starts for the first time. In a read only situation, you can just use the database from the bundle.

Core Data Alternatives on iOS

I've been developing several iOS applications using Core Data and it has been an excellent framework to work with. However, I've encountered an issue whereby we more or less have distributed objects (synced) across multiple platforms. A web/database server backend and mobile devices.
Although it hasn't been a problem until now, the static nature of the data model used by Core Data has me a little stuck. Basically what is being requested is a dynamic forms system whereby forms can be created on a server and propagated to the devices. I'm aware of the technique for performing this with a set number of tables with something like:
Forms table
Fields table
Instance of Forms table
Instance Values table
and just linking everything together. What I'm wondering however is if there is an alternative system to Core Data (something above talking to an SQLite database directly) that will allow for a more dynamic object graph. Even a standard ORM would be good if there are options for modifying the schema at runtime. The main reason I want to go down this route is for performance in the sense that I don't want the instance values table exploding with entries (on the local device or server).
My other option is to have the static schema (object-graph) on the iOS devices but have a conversion layer on the server's side which fetches the correct object, populates the properties and saves it to the correct table. Then when the devices comes to sync, it does the reverse and breaks it down into instances. While this saves the server from having a bloated instance value table, it could still be a problem on the device.
Any suggestions are appreciated.
Using specific tables/entities for forms and fields, and entities for instances of each, is probably what I would recommend. Trying to manipulate the ORM schema on the fly if it's going to be happening frequently doesn't seem like a good idea in general.
However, if the schema is only going to change infrequently, you can probably do it with Core Data. You can programatically create and/or manipulate the NSManagedObjectModel prior to creating a NSManagedObjectContext. You can also create migration logic so data stored in an old model can be preserved when you update the model and need to recreate the context and stores.
These other SO posts may be helpful:
Customize core data model at runtime?
Handling Core Data Model Changes
You need to think carefully about what you are actually modeling.
Are you modeling: (1) the actual "forms" i.e. UI elements, (2) data that might be presented in any number of UI versions e.g. firstName or (3) both?
A data model designed to model forms would have entities like:
Form{
name:string
fields<-->Field.form
}
Field{
width:number
height:number
xPos:number
yPos:number
label:sting
nextTab<-->Field.priorTab
priorTab<-->Field.nextTab
form<<-->Form.fields
}
You would use this to store data about form as displayed in the user interface. Then you would have a separate entities and probably a separate model to store the actual data that would populate the UI elements that are configured by the first data model.
You can use Core Data to modeling anything you just need to know what you are really modeling.

Storing default instances of an NSManagedObject in every new file

I have a core data document based application. Part of my model works by having a DeviceType table, and a Devices table with a relation between them. I would like my application to be able to store the list of DeviceTypes separately from each file, and possibly be able to sync that to a server later.
What would be the best way to accomplish this?
Thanks,
Gabe
You're using a lot of database terminology with Core Data. You should break that habit as soon as possible (the reasons why are given in the introductory paragraphs to the Core Data Programming Guide).
I assume your "usually-static" device list is something you want to be able to update as new devices come out? I would actually recommend just storing the list as a PLIST resource in your app bundle and pushing an update to the app when new devices come out (for simplicity). Using a dictionary-based PLIST, your keys can be device IDs and that key can be a simple string attribute of your managed objects. It's perfectly reasonable to look things up outside your Core Data model based on some ID.
If you must update, I'd still include the "default" list with the app (see above) but if a ".devicelist" (or whatever) file is present in the documents folder, use that instead. That way you can periodically check for an updated list and download it to the docs folder if it differs.
If I've misunderstood you, I encourage you to clarify either by editing your question or posting comments.

Can I have multiple Core data handlers for one iphone app?

I'm wanting to build an app with 2 core data handlers for one iphone app.
The app will be a sports game with pre-filled information. Lets call it prefilledDB as a reference. This prefilledDB will be read-only, I do not want the user to add/edit/delete or change anything in this.
The second db ("gameDB") would have the same core data relationships/models/entities and structure.
When a user selects "New game", it will blank/empty the gameDB and fill it up with the prefilledDB contents, and "Continue game" would just use prefilledDB, assuming it is not empty.
However, I'm not sure if this is the right way to do it. My question therefore is what is the best way to handle this kind of processing. Would an in-built migration system be better than dropping/recreating databases -- or perhaps just using SQLite as the prefilledDB and then filling the gameDB with its contents?
Any help on this would be great.
The prefilled persistent store will have to be readonly if it ships in the app bundle as everything in the app bundle is read only. To make use of the data in a readwrite persistent store, you will need to copy the data to persistent store outside the app bundle e.g. in the documents directory for the app.
You have two ways of doing this:
1) Simplest: Create a new persistent store for each game. In this case you would just copy the prefilled persistent store file from the app directory to the documents directory while in the process renaming it to the current game name. Then you would open that file as the gameDB and it would be automatically populated with the preexisting data. The downside of this system is that you have a large number of files, one for each game, and the data could not be easily shared between them.
2) Best: You use two persistent stores simultaneously in the same context. This is more complicated to set up but gives you greater flexibility. The trick is to create a single abstract subentity e.g. Opponent and then two concrete subentities that are identical save for their names e.g. PreOpponent and GameOpponent. Using the configurations option in the data model, assign PreOpponent to the prefilled persistent store and GameOpponent to the gameDB persistent store. Write some code in the Opponentclass to clone itself to a new GameOpponent instance. When a new game starts, clone all the instances from prefilled to 'gameDB'. All the newly cloned GameOpponent instances will automatically write to the gameDB persistent store.
The advantage of the latter system is that you have all your active data in one readwrite persistent store which you can then manipulate as needed. E.g. you could check previous game or even clone a previous game to create a novel starting point for a new game.
Marcus Zarrus had some code on his site showing how to set up automatic cloning for managed objects.