« Loading and Unloading .Net assemblies | Main | Interprocess Communications Using Shared Memory »
Sunday
Feb072010

UITableView and Core Data

In previous posts I covered using UITableView for displaying structured data, stored in a plist file.  In this article I will present a sample application that uses UITableView and core data to display data stored in a SQLite database.  This application will log  and display in a UITableView blood pressure samples created by the user.  It will store the date and time, the systolic and diastolic values and the pulses per minutes.  The following images show the data collection and the main tableView screens.

Lets start by creating a new project using the Navigation-based application template and make sure that "Use Core Data for storage" is checked.  

I will add and explain the most common code fragments used in this type of applications.  For this application I need to design a data model for the database store.  The data model will have one managed object and this object will have the following attributes: timeStamp, systolic, diastolic and pulsePerMin.  I will create a custom UIView in interface builder that will have three text fields and three labels, each corresponding to the data model's managed object attributes.  

First the data model must be designed.  Click the disclose triangle for the Resources folder and double click on the MyBloodPressure.xcdatamodel file.  This is the default file created by the project template, therefore you should see a window similar to image below.  Select the Entity object, delete it and add a BloodPressure object to the model.  Click on the plus symbol in the first pane to create a new entity.  A new entity is created and added to the model created in the bottom pane.  Now change the name of the object to BloodPressure using the third pane on the top.  Add the systolic, diastolic, pulse, and timeStamp attributes to the object by clicking on the plus symbol in the middle pane.  On the third pane  select the type and uncheck the optional checkbox for each attribute.  Use string type for systolic, diastolic and pulse attributes and use Date type for timeStamp.  Save your work.  

 

The project template created the application delegate class MyBloodPressureAppDelegate and generated all the necessary code to setup core data.  It generated code to load our data model and create a managed object model.  It also generated code to create the persistent store coordinator and the managed object context.  

 The  persistent store coordinator associates persistent stores, (i.e. the MyBloodPressure.sqlite database) with a data model and coordinate access to the store.  The managed object context interact with the persistent store coordinator to save object graphs to persistent storage and to retrieve model information.  Once these objects are setup you mostly interact with the manage object context to do typical CRUD operations.

The MyBloodPressureAppDelegate’s applicationDidFinishLaunching method assigns the navigationController’s topViewController to rootViewController and set the rootViewController’s managedObjectContext.  This is it for MyBloodPressureAppDelegate.

Open the RootViewController.m and find the viewDidLoad method.  This method adds  the “Edit” ,  “+” buttons to the navigation bar and sets up the action function to call when the “+” button is pressed.  The “Edit” button default behavior is handled by the navigation controller and tableView which will give us the standard editing functionality built into the UITableView.  Modify the method to add the following line of code

 self.title = @"Blood Pressure";

This navigation controller by default will use the "title" to display it on the navigation bar when the view is displayed.

 

Now create a new UIViewController with Xib for user interface and name it AddBloodPressureViewController.  Open AddBloodPressureViewController.xib in interface builder by double clicking on the file.  Create the user interface displayed in Figure above.  Save your work, switch back to Xcode and open AddBloodPressureViewController.h.  Modify the code to match the code in figure below. 

 

 

 

 

 

 

 

 

 

 

 

 

 As you can see the class conforms to the UITextFieldDelegate and I added three UITextField fields with the corresponding properties.  Added three boolean variables to enable the “Save” button when the three text field have been edited.  The last two member variables added are of type NSFetchedResultsController and a NSManagedObject.  

Now lets go back to Interface Builder and open AddBloodPressureViewController.xib.  Make sure the UITextFields are connected to the IBOutlets defined in the interface header file and that the FileOwner is the delegate for each UITextField (i.e. see the image above).  Proceed to add a Custom Button and resize it to cover the entire client  area.  Verify that the custom button is selected and click on the “Layout” menu then select “Send To Back” menu entry.  The reason to have this large button is so that we can hide the keyboard when the user taps on the background of the view.  When the user selects a text field the keyboard is shown automatically but in order to hide the keyboard we need to send a resignFirstResponder message to the text field in focus.  To do this the user needs to select another text field or tap on the view background, by tapping on the background the action associated to the custom button is invoked.  Therefore the IBAction resignToKeyboard will hide the keyboard by sending a resignFirstResponder to each of the text fields.  Make sure the the the custom button’s event "Touch Inside" is connected to the IBAction resignToKeyboard.  Save your Interface Builder work and go back to Xcode.

 

 

In the RootViewController's method "insertNewObject" is called when the “plus” button is pressed.  This method instantiates an AddBloodPressureViewController, sets the fetchResultsController and pushes the controller into the navigationController.

Since the RootViewController inherits from UITableViewController is conforms to the UITableViewDataSource and UITableViewDelegate protocols, it also conforms to the NSFetchedResultsControllerDelegate protocol.  Therefore, the didSelectRowAtIndexPath: delegate method is implemented on line133 (above code fragment).  Here I create an AddBloodPressureViewController set its fetchedResultsController and set its managedObject property with the selected object and pushe the controller into the navigationController.

 

 

 In the figure above I implement the NSFetchedResultsControllerDelegate protocol.  Since NSFetchedResultsController is the mediator between CoreData and UITableView it facilitates all CRUD operations and it is also responsible for notifying the UITableView of such activities. On line 238 I implement the NSFetchedResultsController:didChangeObject delegate method to handle NSFetchedResultsChangeType (i.e. Insertions, deletions, updates and moves).

The code shown above is for AddBloodPressureViewController viewDidLoad method.  In this method a "Save" button is created and added to the navigation bar.  If the user selects a row to change the values then the textField objects are set to the respective managedObject values.  If the user is adding a new object then initialize the state to reflect user selection.

 

Once the user has added or modified the values, he or she will press “Save” and managedObject is set to the values collected in the text field UI objects.  The managedObject is then saved permanently by sending a save message to the managedObjectContext object.

That's it!

Hope this helps.  The code can be downloaded here.


PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (3)

Loved the tutorial... but can not get the SAVE button to work. I am going crazy. I have made sure that in interface builder I pointed it back to the resignkeyboard method but still when I enter the values... and hit the back ground button... SAVE button does not become active. what am I missing?

July 18, 2010 | Unregistered CommenterDean-O

Thanks a lot for the post. Also make sure to check out sensiblecocoa.com, I believe they did some really good job in that area.

September 20, 2010 | Unregistered CommenterMatt

Thaaaaaaaaaaanxxxxxxx a lot:)
that was a great tutorial. it helped me a lot in my project..
Keep up the good work;)

Thanx again:)

January 15, 2011 | Unregistered CommenterENG

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>