Modèle CoreData du code. Ou "Comment faire sans .XCDataModel" (Partie 1)

Si pour une raison quelconque, vous n'aimez pas le processus de création d'un modèle coreData à l'aide de l'interface graphique Xcode, ou si vous êtes un programmeur aussi fou que je veux que votre application se débarrasse des fichiers .XCDataModel et s'exécute un peu plus rapidement, alors bienvenue dans cat.


Bref historique


Il y a environ six mois, je développais ma propre application pour iOS, et jusqu'à récemment, le processus de développement s'est déroulé sans heurts et sans aucun problème dans le domaine du stockage de données.


Mais récemment, le modèle coreData a atteint des tailles indécentes de mon point de vue, et comme je suis aveugle, il est physiquement difficile pour moi de travailler avec une grande quantité de données semi-visuelles, j'ai décidé de transférer tout ce qui concerne coreData dans le code.


Il y a très peu de matériel sur le travail "non visuel" avec coreData, donc la moitié de mes conclusions et développements sont basés sur des expériences folles sur Playgrounds et des tentatives non moins folles de google sur les informations manquantes.


En général, c'est parti!


Commençons par les cours.


Si dans un travail standard avec coreData, nous décrivons toutes les entités et les relations entre elles dans un fichier séparé avec le modèle, alors dans notre cas, nous aurons besoin de classes qui décrivent ces entités en premier (il sera plus facile de comprendre avec quoi nous travaillons et Xcode vous aidera, demandant les noms des classes déjà créées).


Soit dit en passant, nous utiliserons ci-dessous un étrange post-script à la fin de chaque classe, "MO" - Objet géré. Cela ne doit pas être confondu avec d'autres classes, peut-être similaires, mais n'est pas lié à coreData.


Nous décrirons la situation suivante:


  • Il existe une entreprise (décrite par la classe CompanyMO);
  • Il y a des employés (décrits par la classe WorkerMO);
  • Chaque employé ne peut travailler que dans une seule entreprise (ou ne pas travailler du tout);
  • Chaque entreprise peut avoir un nombre illimité d'employés (y compris aucun employé).

@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. Facultatif, mais vous pouvez toujours lire sur NSPersistentContainer et son initialiseur init (name: managedObjectModel :) .

All Articles