• 20 hours
  • Medium

Free online content available in this course.

Videos available in this course

Certificate of achievement available at the end this course

Got it!

Last updated on 4/24/18

Implement data controller

Log in or subscribe for free to enjoy all this course has to offer!

We have our data model set up, now we need to prepare our code to be interactive.

Remember the MVC pattern? We already have a controller in our project, however, let's remember, that that is primarily a View Controller.

Can we place the code in ViewController.swift?

We could incorporate our code related to managing data in ViewController.swift - it's a controller file after all. This is especially tempting while implementing simple apps - single view that will handle all data manipulations.

I strongly advice against it :ninja:!

Incorporating a scope of non-view controlling related functionality in ViewController is what earned a non-flattering reputation for MVC pattern :'(.

On top of that, once we have more than one view controller that needs access to data - we are in trouble!

So, here we're moving on to creating a data controller :zorro:!

Creating Data Controller

To handle data managing part we'll create a Data Controller class. It will be responsible for establishing a connection with data and managing it to support the app functionality.

Create a file  DataController.swift , import UIKit and CoreData frameworks and declare a DataController class:

import Foundation
import UIKit
import CoreData

class DataController {
    
}

Next, let's get familiar with the basic mechanics of the CoreData framework.

Core Data Stack

Here we need to learn about Core Data Stack

What's Core Data Stack o_O?

The stack includes a collection of Core Data framework objects that are necessary to access the data store.

Which data store :euh:?

Data store is where the actual data resides. Persistent data store is basically data stored on the device hard drive and is accessible after the app relaunches.

You are already familiar with a possibility of storing flat structures of data for your app suing User Defaults. This time we are referring to an ability of storing structured data - such as multiple records of mood logs. This type of data store is refereed to as Database.

Core Data is using SQLite as it’s persistent store.

What's SQLite :colere:?

Alright, let's back up a bit.

Database + Management System

It's time to mention one of the most common database types - relational database. (and, database is simply a data storage). In fact, there are 3 major types of databases:

  • Relational - strictly structured groups of records called tables. Records in tables all have the same attributes. And tables are connected to each other by one or more attributes, ultimately creating relationships between records.

  • Graph - a more sophisticated version of relational type.

  • Document based - a flat structure of records with various attributes. Typically different records may have different attributes. It's very similar to paper documents in a stack.

All 3 types have a set of rules to follow, some are more flexible than others. Each type provides vast advantages for different contexts and serves as a suitable solution for different problems.

Here's a simplified visualization of the types described above:

Database types diagram
Database types diagram

The database itself is a way of structuring data. On top of it there's a management layer, called Database Management Systems (or DBMS for short). This layer provides tools to manage the data - create, update, delete and fetch (or query) based on certain criteria. In software terms, it's a library that provides interface (Application Programming Interface - API) to manipulate the data. 

Often, when we use the term Database, we mean DMBS.

So, SQLite is a very light weight simple transactional DBMS. The name comes from a composition SQL + Light, or, fancy spelling - Lite >_<.

Another new term - SQL! It stand for Structured Query Language. It's a general term wildly used to describe general approach to work with relational databases.

SQLite supports its own version of SQL.

Core Data + SQLite

Back to Core Data. Core Data is a framework that helps manage object-graph and is using a relational SQLite as its persistent store. Well, after all, graph is a more sophisticated version of a relational structure.

Let's understand the objects of Core Data framework we'll need to work with, those are:

  1. Managed Object - represented by  NSManagedObject  class. An instance of NSManagedObjectModel represents an entry in our entity store - a record of Mood log for example. This instance is responsible for managing individual entry.

  2. Managed Object Context - represented by  NSManagedObjectContext  class. An instance of NSManagedObjectContext represents working canvas for an app in context of data management. It's responsible for managing a collection of managed objects - instances of NSManagedObjectModel.

  3. Persistent Store Coordinator - represented by  NSPersistentStoreCoordinator  class, it references Managed Object Contexts and is responsible for coordinating the operations in contexts applied to persistent store.

  4. Persistent Container - represented by  NSManagedObjectModel  class. It represents the data model.

Let's visualize this schematically:

Core Data objects
Core Data objects

At this point of Swift development, we can implement basic access to all of this quite easily.  We'll also learn a couple of new objects along the way.

Let's start by declaring variables in our data controller class to access context and entity.  And, as a little optimization, we'll have our Mood entity name stored in a constant:

class DataController {
    var entityName = "Mood"
    var context: NSManagedObjectContext
    var entity: NSEntityDescription?
}

The context is described by NSManagedObjectContext type and the entity by a new type - NSEntityDescription. The entity variable is also optional - in case it's not there, we can't replace it with any generated value :waw:.

Next, let's initialize those by implementing a data controller initializer:

    init() {
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        context = appDelegate.persistentContainer.viewContext
        entity = NSEntityDescription.entity(forEntityName: entityName, in: context)
    }

The context object is available through persistent container of an app delegate. And an app delegate is accessible to as via shared property of UIApplication class.

What's shared :euh:?

A term shared in software typically refers to objects that implement Singleton code design pattern - one of the creational design patterns - responsible for how objects are created. It ensures that there could be only ONE instance of a class in the whole application.

Next, to earlier refer to our mood variations, it makes sense to create an enum with raw values as strings:

enum Emotion: String {
    case happy = "Happy"
    case neutral = "Neutral"
    case sad = "Sad"
    case snooze = "Snoozing"
}

Could we name our enum Mood?

At this moment we have to use a name different from Mood, as Mood is already taken by the class name for our Mood entity that we covered in previous chapter. If we try, the names will conflict and we'll get an error.

Defining Data Controller functionality

Public functionality

For now, our data controller class needs to do only one thing to support functionality of our main screen, that is - to log a daily emotion! So, let's create a method for it:

func log(emotion: Emotion) {
    // perform emotion logging for the day
}

Now, let's switch to the view controller. Here we need to declare a variable for data controller:

let dataController = DataController()

And, log emotions when user clicks mood buttons on a screen:

@IBAction func moodButtonPress(_ sender: Any) {
        var emotion = Emotion.snooze
        
        switch (sender as! UIButton).tag {
        case 0: emotion = Emotion.happy
        case 1: emotion = Emotion.neutral
        case 2: emotion = Emotion.sad
        case 3: emotion = Emotion.snooze
        default: return
        }
        
        dataController.log(emotion: emotion)
        //update label
        moodLabel.text = emotion.rawValue + "..."
    }

As you may notice, we've used tag value of the sender button to identify which button was pressed.

Of course, we need to do a bit more work within our controller, the fun part is that no other objects need to know about it :pirate:!

Private functionality

Private functionality of our data controller needs to do some heavy lifting. In particular:

  • To log selected emotion, check if we already created a log for the day and update it with the new emotion.

  • If no record exists - create a new one and assign selected value.

  • Save new or updated object to the store.

And this is what we're going to do in the next chapter :ange:!

Let's Recap!

  • There are 3 main types of databases: Relational, Graph and Document-based.

  • A data managing layer that implements data API is called Database Management System (DBMS)

  • CoreData is using SQLite as its persistent store

  • SQL is a Structured Query Language that is used to communicate with a database

  • There are 4 primary objects of Core Data:

    • Managed Object

    • Managed Object Context

    • Persistent Store Coordinator

    • Persistent Container

Example of certificate of achievement
Example of certificate of achievement