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

Published by

on

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)

8 responses to “Swift 2 examples – #9 Core Data. Create, get, update and remove entities”

  1. JC Avatar
    JC

    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

    1. Nikunj Rajyaguru Avatar
      Nikunj Rajyaguru

      Hey, Have you got any solution for first question.?

      Like

  2. Juan Carlos Sánchez Avatar

    Hi,

    1) Make sure that NSManagedObject is not a base class of PersonService. You can find my PersonService class here: https://gist.github.com/softwarejc/99fb60eef461b356e0a3

    2) The idea of saveChanges is that you can do changes to your context and save to the database when you want.

    I hope that help you!

    Thank you for your comment and have fun with Swift!

    Like

  3. Mark Hardy Avatar

    How does one actually access the data in their attributes using the get functions though?

    Like

  4. Hoang Luu Huy Avatar

    Thank you for a great post.

    Like

  5. zeeshan Avatar
    zeeshan

    Its a good and very useful tutorial. If you could update it for Swift 3 and XCode 8, it would be great.

    Like

  6. Nancy Avatar
    Nancy

    Thanks, it helps me a lot, I just wonder if there multiple model, and their fields are different, I should create many services to meet it , or is there good solutions?

    Like

  7. Jatin Garg Avatar
    Jatin Garg

    Really a great tutorial all at one Place , Really Thanks Best Core data Tutorial I had seen , Any Updated link for core Data relationships ? if yes, Would love to check out

    Like

Your feedback is important…

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Blog at WordPress.com.