Friday, November 9, 2012

Add Core Data to Single View Application Tutorial (View-based application)

This post is written by beginner for beginners so there will be no in depth explanations. The purpose is to equip your app with Core Data as quickly as possible. You can use it to add Core Data to new or existing application.
As you might noticed, there is no built in template for single view application that integrates Core Data. To achieve such a capability we have to do few easy steps:
  1. create Entity with attributes and relationships to represent of our data (you can think of this as creating database layout)
    • create Entity object classes
  2. add Core Data framework to our TARGET (use pre-written tools to make our life easier)
  3. implement necessary code to allow our ViewController to communicate with database.
In this post I'll explain only how to access data in database.
At the end of this tutorial you'll end with application that outputs all your database rows in text view like this:


So lets begin.

0. Create new Single View Application

This tutorial is done on Xcode Version 4.4.1, so some of the screenshots may differ from those on your machine.
If you have existing application skip to step 1.


Write down Product Name and select Automatic Reference Counting



1. Create Entity

In this part of tutorial we'll create model to represent our data. There's also a few new terms which I'll try to explain using database notation.

You can think of Core Data as a middlemen between your application and your data (usually stored as SQLite database).
Model is collection of entities. Entity is blueprint for your objects with its attributes and relationships . This two lines can be thought as a Model is your database. It is consisted of tables - entities, and each row in table is object with its attributes (each attribute is represented as column or relationship in table).

Perhaps, if we want to build application that holds information about Star Trek androids we might create database that contains only one table MrDataEntity and three columns: androidId , androidName , productionDate .


Now lets create our MrDataModel. Go on and create new file as shown bellow.




New file will appear in your projects tree with file extension xcdatamodeld - that's our (empty) Model. Now lets add some entities. Well create an entity called MrDataEntity with three attributes: androidId (type int16), androidName (type String), productionDate (type Date).


If you select your entity now (MrDataEntity) you can see in right panel that it is declared as NSManagedObject class. That's OK, but if you leave it like that you must access your attributes via key string value. (If you don't have right panel shown on screen just press command+option+0).


Better approach is to generate Entity specific class, and thanks to Xcode we do that in just a few simple clicks. Go on and create new file, select Core Data and NSManagedObject subclass. Depending if your Entity was selected before creating new file, next two windows might not appear for you. At the end, click Create and two new files will be listed in your project tree MrDataEntity.h and MrDataEntity.m. They contain properties declarations for MrDataEntity.





(If your run your application now, you'll just get a blank screen.)

2. Add Core Data framework to our TARGET

Next step is to add Core Data framework.

From left panel select root of your project tree and then select your target. Make sure you are on Summary tab and scroll down to Linked Frameworks and Libraries. Now click on + button to add framework.


The window with all available frameworks will appear. Filter the list by typing data in search field. Now select CoreData.framework and click Add. There should be new toolbox icon in Linked Framework and Libraries list and also one on top of your project tree in left panel (you can drag it in Frameworks group).



3. Implement necessary code

All you did in previous two steps didn't affect our application in any way. There wasn't even any "hard copy" database created.

If you don't want to write import core data header file in each file, you can do it only once and it will be imported project wide. Locate file with extension pch (in our case MrData-Prefix.pch inside Supporting Files group) and add this line #import <CoreData/CoreData.h>
Core Data requires three things: NSManagedObjectModel, NSManagedObjectContext, NSPersistentStoreCoordinator. Here's brief description taken from Apple developer site:
  • NSManagedObjectModel - object describes a schema collection of entities (data models) that you use in your application
  • NSManagedObjectContext - scratch pad in an application. Its primary responsibility is to manage a collection of managed objects.
  • NSPersistentStoreCoordinator - mediate between the persistent store and the managed object context or contexts.
Let's open our AppDelegate.h and add these lines before @end.
Now open AppDelegate.m and after @implementation AppDelegate add:
In the same file add this big chunk of pre-boiled Apple's Core Data code:
There are two things in above code you must edit according to your files naming. First is the name of your bundle in managedObjectModel method. It must be the same as you named your model previously (file with .xcdatamodeld extension).
Second one is opinial, that's database name in persistentStoreCoordinator method.
For test run, add just one more line to application didFinishLaunchingWithOptions method before return statement:
If you run your application now it will still be blank, but now we've created hard copy of our database. To locate it go on and add this line to  persistentStoreCoordinator method right below storeURL declaration.
It will print out the path to your application in Simulator folder four your machine.

Since our application is empty we will manually add few rows to it. We could do that from sqlite3 terminal, but we'll use nice free plugin for Firefox called SQLite Manager https://addons.mozilla.org/en-us/firefox/addon/sqlite-manager/

Install and start SQLite Manager plugin.


Click on Open button, press Command + Shift + G on keyboard and write down the path to your database (printed earlier with NSLog in Xcode output panel). Mine is: /Users/XXXXX/Library/Application Support/iPhone Simulator/5.1/Applications/ . Hit enter and chose appropriate UUID for your app (also listed in Xcode output panel), go to Documents and there's our database.


To add rows to it, in left panel, select Tables and table named same as your Data Model file (.xcdatamodeld). Click Add button on right side and input form will appear.


It's time to write print those records in our app!

Open AppDelegate.m and import "MrDataEntity.h".
Now replace line we added earlier in application didFinishLaunchingWithOptions method with lines bellow. Watch out to write appropriate entityForName (in our case that was: MrDataEntity).
You should see our data printed in output panel!


Connect ViewController with our data

Final step of this tutorial is to connect our ViewController with our data. To do so we need to declare NSManagedObjectContext property in ViewController.h file. Add this line before @end statement:
And add this line to AppDelegate.m file -  application didFinishLaunchingWithOptions method before: [self.window makeKeyAndVisible];
You can cut the code for fetching and printing results and paste it in to the ViewController.m to viewDidLoad method. Also add import statement for entity description header file and synthesize  managedObjectContext. Here is how it would look like if we want to print out our data to UITextField:
Here's a running application:


That's all for today!

2 comments:

Unknown said...

Superb bro and thanks for your help

Unknown said...
This comment has been removed by the author.