13

In the Core Data lecture from Stanford 193P iPhone course on iTunes, the instructor coded up a sample project with Core Data without using NSPersistentStoreCoordinator and loading it with a NSManagedObjectModel. But in looking at other code samples and the Big Nerd Ranch book on iPhone development, they are creating a NSManagedObjectModel and PersistentStoreCoordinator and setting up the NSManagedObjectContext that way.

My question is what is the purpose of doing it this way, and what are the pros and cons of both approaches?

Juicy Scripter
  • 25,778
  • 6
  • 72
  • 93
user1337645
  • 473
  • 8
  • 16

2 Answers2

19

I followed the same lecture series very closely. This particular example pulls data (Photographers and Photos) from Flickr and loads them into CoreData. It wasn't really necessary to use CoreData in this app since it needs to fetch new data from flickr on every application load, therefore there is no point in saving persistently. The prof was just using the flickr fetching app from the previous demo as a starting point since students were already familiar with it (allowing him to focus on explaining CoreData). However, as rickster mentioned, there are huge benefits to using core data without saving the context to disk.

As Paul explained in the lecture before the demo, a core database can be created (in iOS5) either by:

  1. Clicking "use core data" for an app template when creating a new project.
  2. Using UIManagedDocument

The idea behind the first approach is that Xcode will put a bunch of code in AppDelegate to set up your documents directory/persistent store coordinator/and model. It will then pass the managed object CONTEXT to your initial view controller (which should have an NSManagedObjectContext property in the public API) and from there you can pass the context around like a bottle of beer when you segue to other viewcontrollers. Passing the context around is correct procedure for accessing the core database.

Using UIManagedDocument is very similar, except your AppDelegate is left alone. You create a UIManagedDocument (maybe in your initial view controller) using a URL path from your app's document directory (Note: you have to manually check to see if the file already exits, exists but is not open, or does not exist). Then you can use this document's context in the same way as above.

Another Note: It's a good idea to create a pointer to your context in your AppDelegate so you are able to explicitly save your context (only when it's ready!) when the app crashes or terminates.

The persistent store coordinator is set up automatically for you and you can configure it using it's persistentStoreOptions property (and indeed you will need to in order to save the context persistently), or by subclassing UIManagedDocument and overriding desired methods.

Read the overview in UIManagedDocument documentation http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIManagedDocument_Class/Reference/Reference.html

Both methods work the same way and provide you with the same control and access. With UIManagedDocuments you can create multiple databases in multiple sqlite files, you can also wait to create / set up the database until it's needed. The "use core data" option provides you with a single core database which it sets up on application load, allows you to centralize CoreData stuff around AppDelegate, saves coding time and is good for a fast-track app. I like UIManagedDocument.

If you started you app without the core data option checked and would like to add it to AppDelegate, just create a new project with core data checked and copy all the code to your AppDelegate (should just be 3 properties and their accessors as well as a convenience method to access the documents directory). You will need to point in to your initial view controller, model, etc..

UPDATE: Just wanted to add one other convenience. If your managed object context is stored in your appDelegate, you can access it anywhere in your app just by using

NSManagedObjectContext* context = [[(AppDelegate*) [UIApplication sharedApplication] delegate] myManagedObjectContext];

this negates having to pass it around.

For any CoreData app, if you make any changes to your model, MAKE SURE TO MANUALLY DELETE THE APP IN THE SIMULATOR before building again. Otherwise you will get an error on the next build since it will use the old file.

Scott Berrevoets
  • 16,921
  • 6
  • 59
  • 80
Patrick Borkowicz
  • 1,206
  • 10
  • 19
  • On top of that long-winded answer I'll add you use a back-pointer to your AppDelegate to grab the context from anywhere, but not preferred approach. – Patrick Borkowicz Jun 27 '12 at 20:58
  • absolutely brilliant answer. In addition to that - here a code snippet to save the UIManahegDocument: [document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL]; – brainray Sep 25 '12 at 09:50
7

Without a persistent store coordinator you will be unable to save your results to a persistent area (database, file, etc)...so if you want a persistent data manager that is utterly useless, then omit NSPersistentStoreCoordinator. Are you sure the project wasn't using it? How was the professor saving the data? When you create a new Core Data project, this logic is autogenerated for you.

EDIT: I got it now, the professor is using UIManagedDocument, which uses its own persistent store coordinator internally (based on the file type) so there is no need to create an explicit one (unless you are not satisfied with the default). So, in the end, its not about whether or not to use a coordinator, it is whether or not you explicitly create it.

borrrden
  • 33,256
  • 8
  • 74
  • 109
  • yes I'm sure the professor wasn't using it, but he was storing objects in core data using [NSEntityDescription insertNewObjectForEntityForName]. Where is the logic autogenerated in? thanks – user1337645 May 24 '12 at 01:24
  • In your App Delegate, I believe. It will set up the store coordinator to be used when you call "Save" on the context. If he wasn't using that function, then why bother with Core Data...I wonder... – borrrden May 24 '12 at 01:40
  • Core Data needs a managed object context, a managed object model, and a persistent store coordinator in order to work. (The `insertNewObject...` method you reference takes a context as parameter, and a context needs a store, and a store needs a model.) What you probably saw in the lecture was the use of a template project -- when you create a new Xcode project and choose "Use Core Data", the `AppDelegate` implementation gets some boilerplate code for setting these up. – rickster May 24 '12 at 05:27
  • 1
    However, it *is* both possible and sometimes desirable to use Core Data without data persistence (that is, without saving data to disk). Without data storage, you still get relationship management, change tracking & undo support, validation, and a number of other features you don't want to implement yourself. In this case, you still use `NSPersistentStoreCoordinator`, but with the `NSInMemoryStoreType`. – rickster May 24 '12 at 05:35
  • Thanks for your reply. The sample project the Stanford professor wrote up seems to be loading from disk just fine. I can tell because the program is written to fetch images from Flickr and store it to disk, and when I relaunch it the data loads instantly vs doing a http fetch. I did not see any boilerplate code in the AppDelegate. The sample project is here: http://www.stanford.edu/class/cs193p/cgi-bin/drupal/system/files/sample_code/Photomania_0.zip – user1337645 May 24 '12 at 07:18
  • @user1337645 That shed some light on what is going on. I updated my answer. – borrrden May 24 '12 at 07:40
  • Utterly useless? We write code every day all day long that stores data in RAM without writing it to the disk. I don't see why core data should be any different. There are plenty of situations where you could use a core data model that is never written to disk. – Abhi Beckert May 13 '13 at 21:51
  • @AbhiBeckert Then it won't be a "persistent data manager" since it will be destroyed once it is finished. I am aware (well more now than when I wrote this answer a year ago) that Core Data has other desirable features besides data persistence but in my case I was looking at it purely from a persistent data manager standpoint. – borrrden May 14 '13 at 01:08