Swift 2 examples – #9 Core Data. Create, get, update and remove entities

This post is part of my collection: Swift 2 – For Beginners.

Core Data is a persistence framework provided by Apple. In this example we will see how to use it in our iOS application. First we will see how to create our data model and then how to perform the following basic operations:

  • Create
  • Get by Id
  • Get all and Get applying a predicate
  • Update
  • Remove

How to create our data model

A data model consist of a group of entities. The concept of entity in Core Data is similar to the concept of table in SQL. Each entity can have attributes in the same way that a table can have columns.

To create a new entity you need a project with Core Data included. Then go to your xdatamodel file and click “Add Entity”, “Add Attribute” to configure it.

To keep the example simple our data model will have one entity with two attributes. A Person with name and age:

Person
-name: string
-age: integer

createEntity

To create a class that represent our data model click on “Editor” > “Create NSManagedObject Subclass…”.
Create NSManagedObject

It should create a class and an extension representing our entity “Person”. To that class we will only add a static field with the entity name, we will use it later to avoid magic strings:

extension Person {
    @NSManaged var name: String?
    @NSManaged var age: NSNumber?
}
class Person: NSManagedObject {
    // Add this line, the string must be equal to your class name
    static let entityName = "Person"
}

managedObjectContext

Before writing code to make our basic operations it is important to know what the managedObjectContext is.

When the project has Core Data Xcode add a bunch of code to our AppDelegate.swift. A piece of that code is the managedObjectContext. This is the object that we need to access the data model. We can get it in our controller with this line of code:

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

To save our changes we always have to call context.save(). It can throw an exception so we have to make the call in a do.. catch.. block:

    // Saves all changes
    func saveChanges(){
        do{
            try context.save()
        } catch let error as NSError {
            // failure
            print(error)
        }
    }

Now we are ready to write our basic functions to access the data model:

Create

    // Creates a new Person
    func create(name: String, age: NSNumber) -> Person {
        
        let newItem = NSEntityDescription.insertNewObjectForEntityForName(Person.entityName, inManagedObjectContext: context) as! Person
        
        newItem.name = name
        newItem.age = age
        
        return newItem
    }

GetById

    // Gets a person by id
    func getById(id: NSManagedObjectID) -> Person? {
        return context.objectWithID(id) as? Person
    }

Get

Now we will see how to get all entities and how to get all entities applying a NSPredicate to our query.

    // Gets all with an specified predicate.
    // Predicates examples:
    // - NSPredicate(format: "name == %@", "Juan Carlos")
    // - NSPredicate(format: "name contains %@", "Juan")
    func get(withPredicate queryPredicate: NSPredicate) -> [Person]{
        let fetchRequest = NSFetchRequest(entityName: Person.entityName)
        
        fetchRequest.predicate = queryPredicate
        
        do {
            let response = try context.executeFetchRequest(fetchRequest)
            return response as! [Person]
            
        } catch let error as NSError {
            // failure
            print(error)
            return [Person]()
        }
    }

Our get all function will be a call to the previous function. The predicate will be a true predicate, to return all objects in our data model.

    // Gets all.
    func getAll() -> [Person]{
        return get(withPredicate: NSPredicate(value:true))
    }

Update

    // Updates a person
    func update(updatedPerson: Person){
        if let person = getById(updatedPerson.objectID){
            person.name = updatedPerson.name
            person.age = updatedPerson.age
        }
    }

Remove

    // Deletes a person
    func delete(id: NSManagedObjectID){
        if let personToDelete = getById(id){
            context.deleteObject(personToDelete)
        }
    }

Complete example:

This class puts all the functions that we have seen before together, we can call it PersonService.

import CoreData

class PersonService{
    
    var context: NSManagedObjectContext
    
    init(context: NSManagedObjectContext){
        self.context = context
    }
    
    // Creates a new Person
    func create(name: String, age: NSNumber) -> Person {
        
        let newItem = NSEntityDescription.insertNewObjectForEntityForName(Person.entityName, inManagedObjectContext: context) as! Person
        
        newItem.name = name
        newItem.age = age
        
        return newItem
    }
    
    // Gets a person by id
    func getById(id: NSManagedObjectID) -> Person? {
        return context.objectWithID(id) as? Person
    }
    
    // Gets all.
    func getAll() -> [Person]{
        return get(withPredicate: NSPredicate(value:true))
    }
    
    // Gets all that fulfill the specified predicate.
    // Predicates examples:
    // - NSPredicate(format: "name == %@", "Juan Carlos")
    // - NSPredicate(format: "name contains %@", "Juan")
    func get(withPredicate queryPredicate: NSPredicate) -> [Person]{
        let fetchRequest = NSFetchRequest(entityName: Person.entityName)
        
        fetchRequest.predicate = queryPredicate
        
        do {
            let response = try context.executeFetchRequest(fetchRequest)
            return response as! [Person]
            
        } catch let error as NSError {
            // failure
            print(error)
            return [Person]()
        }
    }
    
    // Updates a person
    func update(updatedPerson: Person){
        if let person = getById(updatedPerson.objectID){
            person.name = updatedPerson.name
            person.age = updatedPerson.age
        }
    }
    
    // Deletes a person
    func delete(id: NSManagedObjectID){
        if let personToDelete = getById(id){
            context.deleteObject(personToDelete)
        }
    }
    
    // Saves all changes
    func saveChanges(){
        do{
            try context.save()
        } catch let error as NSError {
            // failure
            print(error)
        }
    }
}

How to use the service:

        // Create an instance of the service.
        let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
        let personService = PersonService(context: context)
        
        // Create
        let juanCarlos = personService.create("Juan Carlos", age: 52)

        // Read all
        var people : [Person] = personService.getAll()

        // Read by id
        let firstPerson = personService.getById(people[0].objectID)!

        // Update
        firstPerson.name = "Juan Carlos Sanchez"
        personService.update(firstPerson)

        // Delete
        personService.delete(firstPerson.objectID)
Advertisements

5 thoughts on “Swift 2 examples – #9 Core Data. Create, get, update and remove entities

  1. JC says:

    Hi Juan, great post, thank you.
    I have 2 questions…

    1.) I get a compile error with my PersonService class:
    class PersonService{

    var context: NSManagedObjectContext <- error says "Stored property 'context' requires an initial value or should be @NSManaged"

    2.) When do we call saveChanges() when using this PersonService?

    Thanks again!

    Like

Your feedback is important...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s