An iOS 7 Core Data Tutorial

From Techotopia
Jump to: navigation, search
PreviousTable of ContentsNext
Working with iOS 7 Databases using Core DataAn Overview of iOS 7 Multitouch, Taps and Gestures


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


In the previous chapter, entitled Working with iOS 7 Databases using Core Data, an overview of the Core Data stack was provided, together with details of how to write code to implement data persistence using this infrastructure. In this chapter we will continue to look at Core Data in the form of a step by step tutorial that implements data persistence using Core Data in an iOS 7 application.


Contents


The Core Data Example Application

The application developed in this chapter will take the form of the same contact database application used in previous chapters, the objective being to allow the user to enter name, address and phone number information into a database and then search for specific contacts based on the contact’s name.

Creating a Core Data based Application

As is often the case, we can rely on Xcode to do much of the preparatory work for us when developing an iOS application that will use Core Data. Currently, however, only the Master-Detail Application, Utility Application and Empty Application project templates offer the option to automatically include support for Core Data.

To create the example application project, launch Xcode and select the option to create a new project. In the new project window, select the Empty Application option. In the next screen make sure that the Devices menu is set to iPhone. In the Product Name and Class Prefix fields enter CoreData, enable the Use Core Data checkbox and click Next to select a location to store the project files. Xcode will create the new project and display the main project window. In addition to the usual files that are present when creating a new project, this time an additional file named CoreData.xcdatamodeld is also created. This is the file where the entity descriptions for our data model are going to be stored.


Creating the Entity Description

The entity description defines the model for our data, much in the way a schema defines the model of a database table. To create the entity for the Core Data application, select the CoreData.xcdatamodeld file to load the entity editor:


The Xcode 5 core data entity editor

Figure 42-1


To create a new entity, click on the Add Entity button located in the bottom panel. Double click on the new Entity item that appears beneath the Entities heading and change entity name to Contacts. With the entity created, the next step is to add some attributes that represent the data that is to be stored. To do so, click on the Add Attribute button. In the Attribute pane, name the attribute name and set the Type to String. Repeat these steps to add two other String attributes named address and phone respectively:


The Xcode 5 core data entity editor

Figure 42-2


The entity is now defined and it is time to start writing code.

Adding a Storyboard to the Project

In order to automatically add Core Data support to our application we had to choose the Empty Application project template option when we started Xcode. As such, we now need to create our own storyboard file and view controller class.

To add a storyboard file, select the File -> New File… menu option and, in the resulting dialog, select the User Interface category from beneath iOS in the left hand panel. In the main panel, select the Storyboard option and click on Next. On the subsequent screen make sure iPhone is selected from the Device Family menu before clicking on Next. Name the storyboard Main, select a location in the project for the new file then click on Create.

With the new Storyboard file added to the project, some additional changes are required so that it is used within the application. First, select the CoreData entry at the top of the project navigator panel to display the General settings screen. In the Deployment Info section, locate the Main Interface property and select the newly created Main storyboard file from the corresponding menu:


Selecting a storyboard file as the main interface in Xcode 5

Figure 42-3


Next, edit the CoreDataAppDelegate.m file and modify the didFinishLaunchingWithOptions method so that it simply returns YES instead of creating a window for the application (since we are now using a storyboard file for the user interface this is no longer needed):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
     return YES;
}

Adding a View Controller

With a storyboard file added and configured into the application, we now need to create a view controller.

Within the Xcode project navigator panel, Ctrl-click on the CoreData folder entry. From the popup menu, select New File.... In the new file panel, select the iOS Cocoa Touch category followed by the Objective-C class icon and click Next. On the following options screen, make sure the Subclass of menu is set to UIViewController and name the class CoreDataViewController. Also, make sure the Targeted for iPad and With XIB for user interface options are off. Click Next and select a location for the new class files before clicking on Create.

All that remains in this phase of the tutorial is to add a UIViewController instance to the storyboard and to associate it with our newly created view controller class. Select the Main.storyboard file and drag and drop a View Controller instance from the Object Library panel onto the storyboard design canvas. Select this new view controller so that it is highlighted in blue, display the Identity Inspector panel and change the Class setting from UIViewController to our new CoreDataViewController class.

The new storyboard file and view controller are now ready.

Designing the User Interface

With the storyboard and view controller configured, now is a good time to design the user interface and establish the outlet and action connections. Select the Main.storyboard file to begin the design work. The user interface and corresponding connections used in this tutorial are the same as those in previous data persistence chapters. The completed view should, once again, appear as outlined in Figure 42-4 (note that objects may be cut and pasted from the previous Database project to save time in designing the user interface layout):

The user interface for an iOS 7 Core Data example app

Figure 42-4


Before proceeding, stretch the status label (located above the two buttons) so that it covers most of the width of the view. Finally, edit the label and remove the word “Label” so that it is blank.

Select the top most text field object in the view canvas, display the Assistant Editor panel and verify that the editor is displaying the contents of the CoreDataViewController.h file. Ctrl-click on the text field object again and drag to a position just below the @interface line in the Assistant Editor. Release the line and in the resulting connection dialog establish an outlet connection named name.

Repeat the above steps to establish outlet connections for the remaining text fields and the label object to properties named address, phone and status respectively.

Ctrl-click on the Save button object and drag the line to the area immediately beneath the newly created outlet in the Assistant Editor panel. Release the line and, within the resulting connection dialog, establish an Action method on the Touch Up Inside event configured to call a method named saveData. Repeat this step to create an action connection from the Find button to a method named findContact.

With the connections established, select the CoreDataViewController.h file and verify the settings are correct before modifying the file to import the CoreDataAppDelegate.h file which will be required by code added to the view controller later in the chapter:

#import <UIKit/UIKit.h>
#import "CoreDataAppDelegate.h"

@interface CoreDataViewController : UIViewController
@property (strong, nonatomic) IBOutlet UITextField *name;
@property (strong, nonatomic) IBOutlet UITextField *address;
@property (strong, nonatomic) IBOutlet UITextField *phone;
@property (strong, nonatomic) IBOutlet UILabel *status;
- (IBAction)saveData:(id)sender;
- (IBAction)findContact:(id)sender;
@end

Saving Data to the Persistent Store using Core Data

When the user touches the Save button the saveData method is called. It is within this method, therefore, that we must implement the code to obtain the managed object context and create and store managed objects containing the data entered by the user. Select the CoreDataViewController.m file, scroll down to the template saveData method and implement the code as follows:

- (IBAction)saveData:(id)sender {
    CoreDataAppDelegate *appDelegate =
    [[UIApplication sharedApplication] delegate];

   NSManagedObjectContext *context =
    [appDelegate managedObjectContext];
   NSManagedObject *newContact;
   newContact = [NSEntityDescription
       insertNewObjectForEntityForName:@"Contacts"
       inManagedObjectContext:context];
   [newContact setValue: _name.text forKey:@"name"];
   [newContact setValue: _address.text forKey:@"address"];
   [newContact setValue: _phone.text forKey:@"phone"];
   _name.text = @"";
   _address.text = @"";
   _phone.text = @"";
   NSError *error;
   [context save:&error];
   _status.text = @"Contact saved";
}

The above code identifies the application delegate instance and uses that object to identify the managed object context. This context is then used to create a new managed object using the Contacts entity description. The setValue method of the managed object is then called to set the name, address and phone attribute values of the managed object (which in turn are read from the text field user interface components). Finally, the context is instructed to save the changes to the persistent store with a call to the context’s save method.

Retrieving Data from the Persistent Store using Core Data

In order to allow the user to search for a contact it is now necessary to implement the findContact action method. As with the save method, this method will need to identify the application delegate and managed object context. It will then need to obtain the entity description for the Contacts entity and then create a predicate to ensure that only objects with the name specified by the user are retrieved from the store. Matching objects are placed in an array from which the attributes for the first match are retrieved using the valueForKey method and displayed to the user. A full count of the matches is displayed in the status field.

The code to perform these tasks is as follows:

- (IBAction)findContact:(id)sender {
    CoreDataAppDelegate *appDelegate =
       [[UIApplication sharedApplication] delegate];

    NSManagedObjectContext *context =
       [appDelegate managedObjectContext];

    NSEntityDescription *entityDesc =
       [NSEntityDescription entityForName:@"Contacts"
       inManagedObjectContext:context];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDesc];

    NSPredicate *pred =
       [NSPredicate predicateWithFormat:@"(name = %@)",
        _name.text];
    [request setPredicate:pred];
    NSManagedObject *matches = nil;

    NSError *error;
    NSArray *objects = [context executeFetchRequest:request
        error:&error];

    if ([objects count] == 0) {
       _status.text = @"No matches";
    } else {
       matches = objects[0];
       _address.text = [matches valueForKey:@"address"];
       _phone.text = [matches valueForKey:@"phone"];
       _status.text = [NSString stringWithFormat:
           @"%lu matches found", (unsigned long)[objects count]];
    }
}

Building and Running the Example Application

The final step is to build and run the application. Click on the Run button located in the toolbar of the main Xcode project window. If errors are reported check the syntax of the code you have written, using the error message provided by Xcode as guidance. Once the application compiles it will launch and load into the device or iOS Simulator. Enter some test contacts (some with the same name). Having entered some test data, enter the name of the contact for which you created duplicate records and click the Find button. As shown in Figure 42-5, the address and phone number of the first matching record should appear together with an indication in the status field of the total number of matching objects that were retrieved:


An iOS 7 Core Data example app running

Figure 42-5


Summary

The Core Data framework provides an abstract, object oriented interface to database storage within iOS applications. As demonstrated in the example application created in this chapter, Core Data does not require any knowledge of the underlying database system and, combined with the visual entity creation features of Xcode, allows database storage to be implemented with relative ease.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
Working with iOS 7 Databases using Core DataAn Overview of iOS 7 Multitouch, Taps and Gestures