Ravi Kumar January 11, 2019

Core Data: Core Data Stack in Swift

Hey Techies

Let’s talk about Core Data today!

What is Core Data?

Core Data is an Apple Framework and it is used to manage data of an application. For example, if an application has users and also posts by those users, Core Data is used to manage users, posts, and relationships between them. It provides the functionality to add, edit, delete and fetch data in a very efficient way.

Core Data Stack

When we are using core data in our application, there are some components of the Core Data which the developers need to know:

  1. NSManagedObjectModel
  2. NSPersistentStoreCoordinator
  3. NSManagedObjectContext

 

NSManagedObjectModel

Core data manages the app data in the form of Entities. Each entity represents a particular type of object e.g. User, Posts, etc. Each entity has its attributes (first name, last name, age, address, etc.) and relations. To manage this information Core Data creates a file in the app bundle named ProjectName.xcdatamodeld. This file is compiled as .momd file by the compiler. In this file, we can create Entities their attributes and relationships between them. The app interacts with this data model using NSManagedObjectModel class. This class loads this file and provides the information of all the entities in the file.

NSManagedObjectContext

When we use an app, we may be presented with all the posts published by users of the app, comments on the posts and various users and categories of posts, etc. Not all the records are loaded into the app. At a particular time, only a few of them are loaded on the app based on user requirements. For example, if the user is viewing the posts of a particular category then only the posts of that category will be loaded onto the app and if the user is viewing the posts of a particular user, the posts related to only that user will be loaded. Now the job of the ManagedObjectContext is to fetch all the required records from the Persistent Store and keep track of them. Once the records are loaded into the ‘Context’, these records can be used by the App.

Now if the app user writes a comment on one of the posts, that comment will be saved into the managed object context first and will be presented to the app from the context itself. The app has to explicitly save this comment into the Persistent store. Once saved in the Persistent store, it can be retrieved any time in the future.

The benefit of ManagedObjectContext is that we do not need to run a query in the Persistent store every time we need some information as the information once loaded into the ManagedObjectContext can be used repeatedly.

NSPersistentStoreCoordinator

The PersistentStoreCoordinator acts as a controller between managed object context and Persistent store. It makes sure that Persistent store and Data models are compatible. It also manages the cache part of the Core data.

An application can have multiple Persistent stores and managed object contexts. However, a typical file usually has only one Persistent store and managed object context.

All this can be depicted in pictorial form as follows:

 

Let us create a demo project to understand it further.

We will create a new single view application (you can create anyone)

Open Xcode -> Create a new Xcode project

In the next screen under iOS -> Application -> Single View Application -> Next

 

In the next screen, we need to configure our project. We will enter the name, team, Organisation name, Organisation Identifier, and the language (Swift for this project). The most important thing that we need to do on this screen is to check the User Core Data checkbox. This will write the basic code to use Core Data in our application. This code is written in the AppDelegate.swift file.

There are four properties that are created by Xcode

  1. lazy var  applicationDocumentsDirectory: NSURL
  2. lazy var  managedObjectModel: NSManagedObjectModel
  3. lazy var  managedObjectContext: NSManagedObjectContext
  4. lazy var  applicationDocumentsDirectory: NSURL
lazy var  applicationDocumentsDirectory: NSURL = {

    let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)

    return urls[urls.count-1]

}()

applicationDocumentsDirectory

This property returns the URL to the document directory of the app. Xcode creates a .sqlite file in this location for the application. This is the file where actual data of the application is saved and is the Persistent store of the application.

lazy var  managedObjectModel: NSManagedObjectModel = {

    let let modelURL = NSBundle.mainBundle().URLForResource("Blogger", withExtension: "momd")!

    return NSManagedObjectModel(contentsOfURL: modelURL)!

}()

managedObjectModel

There is another file which is created by Xcode for the application Blogger.xcdatamodeld

This is the file where we create our entities and their attributes.

managedObjectModel property loads this file.

lazy var  persistentStoreCoordinator: NSPersistentStoreCoordinator = {

    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("ProjectName.sqlite")

    var failureReason = "There was an error creating or loading the application's saved data."

    do {

    try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)

    } catch {

    var dict = [String: AnyObject]()

    dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"

    dict[NSLocalizedFailureReasonErrorKey] = failureReason

    dict[NSUnderlyingErrorKey] = error as NSError

    let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)

    NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")

    abort()

    }

    return coordinator


}()

persistentStoreCoordinator: This property returns the Persistent store coordinator of the core data stack

First, we initialize the coordinator with the managedObjectModel we created in the previous step

Then we get the Url to the .sqlite file. This is the file where actual data is saved

try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: Url, options: nil) 

In this line, the Persistent store is added to the coordinator. 

If for some reason any error occurs there, it will be displayed and the application will terminate or abort().

It is up to you whether you want to terminate the application or do something else. 

If everything goes well, then persistentStoreCoordinator is returned

lazy var  managedObjectContext: NSManagedObjectContext = {

    let coordinator = self.persistentStoreCoordinator

    var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator

    return managedObjectContext

}()

To create a managed object Context property, we need to specify the following:

NSManagedObjectContext instance. In this instance, we specify the concurrencyType property

It has two values:

.MainQueueConcurrencyType
.PrivateQueueConcurrencyType 

MainQueueConcurrencyType specify that context will work on the main thread of the application

PrivateQueueConcurrencyType specify that context will work on some private thread created by user

Persistent store coordinator is assigned to the managedObjectContext

Up Next

In this article, we have learned about the Core Data Stack basics. In the next article, we will study various parts of ManagedObjectModel.

Found the article useful? Share it with your friends and co-workers… Now!

If you have any queries or doubts about this topic please feel free to contact us. We are here to help you!

Lets’s Talk

About your ideas and concept