Introduction

Core Data is the framework in iOS SDK that is used for permanent data storage for iOS apps. Essentially a SQLite database but embedded into the iOS developing environment in Xcode, it greatly simplifies the process of data management for personal-level apps.

If Core Data is included in an iOS project, the entire database should be found by a xcdatamodeld file. It is consisted of multiple entities and relationships between them, in which are attributes for each entity. An entity is analogous to a class in memory-based programming, and each attribute in an entity is like a variable in that class. When storing data to one entity, the program is basically “instantiating” an object of this “class”, and gives values to those “variables”. All objects of different entities could be stored in a NSManagedObject array, which is a dictionary-like data structure.

An Example

We are creating a database for all activities in a college campus, with every activity having a holder, a description and a date. First we create an Activity entity and it has attributes holder, descript and date. Suppose two activities are added to the database; the data structure will look like this:

An `NSManagedObject` array of entity `Activity`; item order does not matter:  
|-------------------------------------------|   |--------------------------------------|
| [holder: String] Jackie                   |   | [holder: String] Max                 |
| [descript: String] iOS Developing Seminar |   | [descript: String] A quick brown fox |
| [date: String] July 4th, 2016             |   | [date: String] February 30th, 2017   |
|-------------------------------------------|   |--------------------------------------|

It is possible to store instantiations of more than one entity in one NSManagedObject array. For example, if we have another entity Course with one object, it can be stored in the previous array:

|--------[Entity: Activity]-----------------|   |--------[Entity: Activity]------------|    |--------[Entity: Course]--------|
| [holder: String] Jackie                   |   | [holder: String] Max                 |    | [name: String] COM SCI 111     |
| [descript: String] iOS Developing Seminar |   | [descript: String] A quick brown fox |    | [numOfStudents: Int] 100       |
| [date: String] July 4th, 2016             |   | [date: String] February 30th, 2017   |    |--------------------------------|
|-------------------------------------------|   |--------------------------------------|

Sample Codes

Continue with our example about activities. Store new activities to Core Data:

var activities = [NSManagedObject]();

func saveActivities(holder who: String, description what: String, date when: String) {
	// define App Delegates
	let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
	let managedContext = appDelegate.managedObjectContext

	// instantiation of an object with entity "Activity"
	let entity = NSEntityDescription.entityForName("Activity", inManagedObjectContext: managedContext)
	let activity = NSManagedObject(entity: entity!, insertIntoManagedObjectContext: managedContext)

	// set values for the activity
	activity.setValue(who, forKey: "holder")
	activity.setValue(what, forKey: "descript")
	activity.setValue(when, forKey: "date")

	// commit unsaved changes to Core Data; add this new object to the array
	do {
		try managedContext.save()
		activities.append(activity)
	} catch let error as NSError {
		print("Could not save activity. \(error), \(error.userInfo)")
	}
}

Fetch all objects of entity Activity from Core Data to memory (to the NSManagedObject array):

func fetchActivites() {
    // define App Delegates
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext

    // create fetch request for an entity
    let fetchRequest = NSFetchRequest(entityName: "Activity")

    // fetch the objects and store them in the array
    do {
        let results = try managedContext.executeFetchRequest(fetchRequest)
        activities = results as! [NSManagedObject]
    } catch let error as NSError {
        print("Could not fetch activities. \(error), \(error.userInfo)")
    }
}

Display an object in a NSManagedObject array to UITableView:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    ... // get UITableViewCell
    let activity = activities[indexPath.row]
    cell.holderLabel.text = activity.valueForKey("holder") as? String
    cell.descriptionLabel.text = activity.valueForKey("descript") as? String
    cell.dateLabel.text = activity.valueForKey("date") as? String
}

When user deletes a cell in UITableView, delete it from both the NSManagedObject array and Core Data:

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
        // Delete the row from the data source
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

        appDelegate.managedObjectContext.deleteObject(activities[indexPath.row]) // delete from Core Data
        do {
            try appDelegate.managedObjectContext.save()
            activities.removeAtIndex(indexPath.row) // delete from "activities" array
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        } catch let error as NSError {
            print("Could not delete the activity. \(error), \(error.userInfo)")
        }

    } ...
}

Future

I am continue exploring how to edit an existing object in Core Data. The editing should be both reflected in the memory-based array of NSManagedObject and Core Data database.

I will end this post with a graph I found pretty useful regarding functions of View Controllers. View Controller Graph