An iOS 9 Core Data Tutorial

From Techotopia
Revision as of 20:00, 27 October 2016 by Neil (Talk | contribs) (Text replacement - "<table border="0" cellspacing="0">" to "<table border="0" cellspacing="0" width="100%">")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
PreviousTable of ContentsNext
An iOS 9 Core Data TutorialAn Introduction to CloudKit Data Storage on iOS 9


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 9 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 9 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. To create the example application project, launch Xcode and select the option to create a new project. In the new project window, select the Single View Application option. In the next screen make sure that the Devices menu is set to Universal and the language is set to Swift. Enter CoreDataDemo into the Product Name field, 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 CoreDataDemo.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 CoreDataDemo.xcdatamodeld file to load the entity editor:


Xcode 6 core data editor.png

Figure 48-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 the 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:


Xcode 6 core data entity attributes.png

Figure 48-2


Generating the Managed Object Subclass

Within the application the data model is going to be represented by a subclass of the NSManagedObject class. Rather than manually write the code for this class, Xcode can be used to automatically generate the class on our behalf. With the Entity editor still displayed in Xcode, select the Editor -> Create NSManagedObject Subclass… menu option to display the dialog shown in Figure 48-3:


Xcode 6 data model selection.png

Figure 48-3


Make sure that the CoreDataDemo data model is selected before clicking on the Next button to display the entity selection screen (Figure 48-4):


Xcode 6 core data entity selection.png

Figure 48-4


Verify that the Contacts entity is selected before clicking on the Next button once again. Within the final screen, set the Language menu to Swift and click on the Create button. A new file named Contacts.swift will have been added to the project containing the NSManagedObject subclass for the entity together with a file named Contacts+CoreDataProperties.swift containing an extension to the Contacts class encapsulating the three data property fields:

import Foundation
import CoreData

extension Contacts {

    @NSManaged var name: String?
    @NSManaged var address: String?
    @NSManaged var phone: String?

}

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

Designing the User Interface

With the entity defined, 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 48-5 (note that objects may be cut and pasted from the previous Database project to save time in designing the user interface layout):


Ios 8 core data ui.png

Figure 48-5


Before proceeding, stretch the status label (located above the two buttons) so that it covers most of the width of the view and configure the alignment attribute so that the text is centered. 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 ViewController.swift file. Ctrl-click on the text field object again and drag to a position just below the class declaration 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 viewDidLoad method 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 saveContact. Repeat this step to create an action connection from the Find button to a method named findContact.

Accessing the Managed Object Context

In order to store and retrieve data using Core Data a reference to the application delegate’s managed object context is required. Within the ViewController.swift file, import the CoreData Framework and add a variable in which to store this reference as follows:

import UIKit
import CoreData

class ViewController: UIViewController {

    let managedObjectContext = 
		(UIApplication.sharedApplication().delegate 
				as! AppDelegate).managedObjectContext

    @IBOutlet weak var name: UITextField!
    @IBOutlet weak var address: UITextField!
    @IBOutlet weak var phone: UITextField!
    @IBOutlet weak var status: UILabel!
.
.
.

Saving Data to the Persistent Store using Core Data

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

@IBAction func saveContact(sender: AnyObject) {
    let entityDescription =
        NSEntityDescription.entityForName("Contacts",
            inManagedObjectContext: managedObjectContext)

    let contact = Contacts(entity: entityDescription!,
        insertIntoManagedObjectContext: managedObjectContext)

    contact.name = name.text!
    contact.address = address.text!
    contact.phone = phone.text!


    do {
        try managedObjectContext.save()
        name.text = ""
        address.text = ""
        phone.text = ""
        status.text = "Contact Saved"

    } catch let error as NSError {
        status.text = error.localizedFailureReason
    }
}

The above code uses the managed object context to obtain the Contacts entity description and then uses it to create a new instance of the Contacts managed object subclass. The name, address and phone attribute values of this managed object are then set to the current text field values. Finally, the context is instructed to save the changes to the persistent store with a call to the context’s save method. The success or otherwise of the operation is reported on the status label and, in the case of a successful outcome, the text fields are cleared ready for the next contact to be entered.

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

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 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 func findContact(sender: AnyObject) {
    let entityDescription =
    NSEntityDescription.entityForName("Contacts",
        inManagedObjectContext: managedObjectContext)

    let request = NSFetchRequest()
    request.entity = entityDescription

    let pred = NSPredicate(format: "(name = %@)", name.text!)
    request.predicate = pred


    do {
        var results = 
             try managedObjectContext.executeFetchRequest(request)

        if results.count > 0 {
            let match = results[0] as! NSManagedObject

            name.text = match.valueForKey("name") as? String
            address.text = match.valueForKey("address") as? String
            phone.text = match.valueForKey("phone") as? String
            status.text = "Matches found: \(results.count)"
        } else {
            status.text = "No Match"
        }

    } catch let error as NSError {
         status.text = error.localizedFailureReason
    }
}

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 tap the Find button. 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.

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
An iOS 9 Core Data TutorialAn Introduction to CloudKit Data Storage on iOS 9