CoreData model from the code. Or “How to Do Without .XCDataModel” (Part 1)

If for some reason you don’t like the process of creating a coreData model using the Xcode GUI, or you are as crazy a programmer as I want your application to get rid of .XCDataModel files and run a little faster, then welcome to cat.


Brief Background


About half a year ago I’ve been developing my own application for iOS, and until recently, the development process went smoothly and without any problems in the field of data storage.


But recently, the coreData model has grown to sizes that are indecent from my point of view, and since I am blind, it’s physically difficult for me to work with a large amount of semi-visual data, I decided to transfer everything that concerns coreData to the code.


There is very little material on "non-visual" work with coreData, so half of my conclusions and developments are based on insane experiments on Playgrounds and no less insane attempts to google missing information.


In general, let's go!


Let's start with the classes.


If in standard work with coreData we describe all entities and the relationships between them in a separate file with the model, then in our case we will need classes that describe those entities first (it will be easier to understand what we are working with, and Xcode will help, prompting the names of already created classes).


By the way, below we will use a strange postscript at the end of each class, "MO" - Managed Object. This is not to be confused with other, possibly similar, classes, but not related to coreData.


We will describe the following situation:


  • There is a company (described by the class CompanyMO);
  • There are employees (described by the WorkerMO class);
  • Each employee can work only in one company (or not work at all);
  • Each company can have any number of employees (including no employees at all).

@objc(CompanyMO)
public class CompanyMO: NSManagedObject {
@NSManaged public var companyName: String
@NSManaged public var workers: NSSet
}

@objc(WorkerMO)
public class WorkerMO: NSManagedObject {
@NSManaged public var firstname: String
@NSManaged public var lastname: String
@NSManaged public var company: CompanyMO?
}

.


objc() — , , .


objc(CompanyMO) CompanyMO , CompanyMO Objective-C CompanyMO. objc(NameOfClass) Objective-C.


— @NSManaged .


@NSManaged , , . , ( Apple, ), @NSManaged coreData.



— , .


, , extension .


extension NSEntityDescription {
convenience init(from classType: AnyClass) {
self.init()
self.name = NSStringFromClass(classType)
self.managedObjectClassName = NSStringFromClass(classType)
}

func addProperty(_ property: NSPropertyDescription) {
self.properties.append(property)
}
}

extension NSAttributeDescription {
convenience init(name: String, ofType: NSAttributeType, isOptional: Bool = false) {
self.init()
self.name = name
self.attributeType = ofType
self.isOptional = isOptional
}
}

.


NSEntityDescription — coreData, (, ). ( , ) (managedObjectClassName), , (, — CompanyMO, WorkerMO ).


, :


let company = NSEntityDescription()
company.name = "CompanyMO"
company.managedObjectClassName = "CompanyMO"

, , NSEntityDescription. , :


let company = NSEntityDescription(from: CompanyMO.self)
let worker = NSEntityDescription(from: WorkerMO.self)

, , .



( , ), .


var model: NSManagedObjectModel {
let _model = NSManagedObjectModel()

let companyEntity = NSEntityDescription(from: CompanyMO.self)
companyEntity.addProperty(NSAttributeDescription(name: "companyName", ofType: .stringAttributeType))
//      CompanyMO.workers,         
let workerEntity = NSEntityDescription(from: WorkerMO.self)
workerEntity.addProperty(NSAttributeDescription(name: "firstname", ofType: .stringAttributeType))
workerEntity.addPropertyNSAttributeDescription((name: "lastname", ofType: .stringAttributeType))

_model.entities = [companyEntity, workerEntity]
return _model
}

.


NSManagedObjectModel entities, NSEntityDescription.


NSManagedObjectModel.entities: [NSEntityDescription]

NSEntityDescription . , , - . , , .


NSEntityDescription , companyEntity workerEntity companyEntity.properties workerEntity.properties, NSPropertyDescription.


NSPropertyDescription NSAttributeDescription ( , , ) NSRelationshipDescription ( ).


NSRelationshipDescription .


, :


  1. CompanyMO WorkerMO;
  2. , . companyEntity companyName ( workers ), workerEntity firstname lastname.
  3. entities "" .

.


.



NSPersistentStore NSPersistentStoreCoordinator NSPersistentContainer (, . ).


coreData .


, ( ) .


persistentContainer .


lazy var persistentContainer: NSPersistentContainer {
let _container = NSPersistentContainer(name: "CyrmaxModel", managedObjectModel: model)
_container.loadPersistentStores {
(description, error) in
//  ,  -
}
return _container
}

, ( ) , .


persistentContainer coreData , .



  1. , ;
  2. (- - , );
  3. ( , "?", ).


, , , , , .


, .


, .


WorkerMO, .


@objc(WorkerMO)
public class WorkerMO: NSManagedObject {
@NSManaged public var firstname: String
@NSManaged public var lastname: String

static private var _entityDescription: NSEntityDescription?
static func entityDescription() -> NSEntityDescription {
guard self._entityDescription == nil else {
return _entityDescription!
}
let des = NSEntityDescription(from: self)
des.addProperty(NSAttributeDescription(name: "firstname", ofType: .stringAttributeType))
des.addProperty(NSAttributeDescription(name: "lastname", ofType: .stringAttributeType))
self._entityDescription = des
return self._entityDescription!
}
}

CompanyMO ( ).


.


_entityDescription , ?


, NSRelationshipDescription .


, , CompanyMO.entityDescription() NSEntityDescription, .



coreData- — . , . ( , StoryBoard, ), .


- , , StoryBoard, XCDataModel.



  1. NSManagedObjectModel;
  2. NSEntityDescription;
  3. NSPropertyDescription NSAttributeDescription;
  4. Optional, but you can still read about NSPersistentContainer and its init (name: managedObjectModel :) initializer.

All Articles