NSManagedObjectModel manages your model schema structure which includes your entities definition and entities relationship.
NSPersistenceStoreCoordinator ensures the consistence of object model schema and persistence store.
NSManagedObjectContext manages the task of CRUD.
They are called Core Data Stack. However, since iOS 10, Apple introduces NSPersistentContainer which simplify the complexity of core data stack and provide ease of use for developers.
However, if you want to understand the how core data stack work, let's see the following code.
1. Create a class called CoreDataManager
import Foundation
import CoreData
final class CoreDataManager {
}
}
*Note: It is not important to use "final"
2. Create a property named "model" and init function to that class
private let modelName : String
init(modelName:String) {
self.modelName = modelName
}
3. Create a function named "createModel"
func createModel() -> NSManagedObjectModel{
let model = NSManagedObjectModel()
// Entity
let entity = NSEntityDescription()
entity.name = "Person"
entity.managedObjectClassName = "Person"
// Attribute
var properties : [NSAttributeDescription] = []
let nameAttr = NSAttributeDescription()
nameAttr.name = "name"
nameAttr.attributeType = .stringAttributeType
nameAttr.isOptional = false
properties.append(nameAttr)
entity.properties = properties
model.entities = [entity]
return model
}
4. Create a lazy property called "managedObjectModel"
private lazy var managedObjectModel: NSManagedObjectModel = {
var objectModel : NSManagedObjectModel?
var modelURL : URL?
if let url = Bundle.main.url(forResource: self.modelName, withExtension: "momd"){
modelURL = url
return NSManagedObjectModel(contentsOf: modelURL!)!
}else {
let fileManager = FileManager.default
do {
let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileURL = documentDirectory.appendingPathComponent("\(self.modelName).momd")
let model = self.createModel()
let modelData = NSKeyedArchiver.archivedData(withRootObject: model)
try modelData.write(to: fileURL)
objectModel = model
}catch let error as NSError {
print("error")
}
}
return objectModel!
}()
5. Create a lazy property called "persistentStoreCoodinator"
private lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let fileManager = FileManager.default
let storeName = "\(self.modelName).sqlite"
let documentsDirectoryURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let persistentStoreURL = documentsDirectoryURL.appendingPathComponent(storeName)
do {
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType,
configurationName: nil,
at: persistentStoreURL,
options: nil)
} catch {
fatalError("Unable to Load Persistent Store")
}
return persistentStoreCoordinator
}()
6. Finally Create a lazy property called "managedObjectContext"
private(set) lazy var managedObjectContext: NSManagedObjectContext = {
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator
return managedObjectContext
}()
Now let's see how it works:
Now let's see how it works:
- First we create a simple class named "CoreDataManager" for creating Core Data, actually.
- We create a string property to store the name of Core Data, the name will be used for both database and file inside the project. One name to rule them all, maybe.
- And we create a function to define a model for our core data. Model contain all entities and relationship.
- We then call the model from the file path in project in case we already have a .momd file. However, in this case, we don't have any file .momd yet. So in "Else" block, we create a file that contain model content from "createModel" function. Then save it to project path and return it.
- So persistentStoreCoordinator just fetch a database file which the table schema based on the managed object model we just created in (4).
- Lastly, "persistentStoreCoordinator" will give model schema and table schema to "managedObjectContext" for data manipulation (Insert, Delete, Update...).
Now let's see how we use this "CoreDataManager" class.
- In AppDelegate, create a property named "coreDataManager"
var coreDataManager : CoreDataManager? - Add the following code to this function
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {self.coreDataManager = CoreDataManager(modelName: "MyCoreData")return true} - Create a view controller class and add this code to "viewDidLoad"
class ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()let appDelegate = UIApplication.shared.delegate as! AppDelegatelet core = appDelegate.coreDataManagerlet e = NSEntityDescription.entity(forEntityName: "Person", in: (core?.managedObjectContext)!)let eObj = NSManagedObject(entity: e!, insertInto: core?.managedObjectContext)eObj.setValue("TestName", forKey: "name")try! core?.managedObjectContext.save()let fet = NSFetchRequest<NSManagedObject>(entityName: "Person")let q = try! core?.managedObjectContext.fetch(fet)for i in q! {let v = i.value(forKey: "name")print("q \(String(describing: v)))")}}}
I don't need to explain the above points since we focus on only Core Data Stack. That's all for Core Data Stack. Here is the full file source code.