It works! (WIP!)

This commit is contained in:
John Estropia
2017-04-04 20:25:40 +09:00
parent 6948db516d
commit 258c237100
4 changed files with 208 additions and 74 deletions

View File

@@ -267,7 +267,7 @@ internal extension NSManagedObjectModel {
}
var mapping = [String: String]()
self.entities.forEach {
self.entities.forEach { // TODO: use AnyEntity as mapping key
guard let entityName = $0.name else {

View File

@@ -51,6 +51,23 @@ public final class DataStack: Equatable {
self.init(model: model, migrationChain: migrationChain)
}
public convenience init(dynamicModel: ModelVersion) {
self.init(model: dynamicModel.createModel())
}
public convenience init(dynamicModels: [ModelVersion], migrationChain: MigrationChain = nil) {
CoreStore.assert(
migrationChain.valid,
"Invalid migration chain passed to the \(cs_typeName(DataStack.self)). Check that the model versions' order is correct and that no repetitions or ambiguities exist."
)
self.init(
model: NSManagedObjectModel(byMerging: dynamicModels.map({ $0.createModel() }))!,
migrationChain: migrationChain
)
}
/**
Initializes a `DataStack` from an `NSManagedObjectModel`.
@@ -510,7 +527,7 @@ public final class DataStack: Equatable {
// }()
private var configurationStoreMapping = [String: NSPersistentStore]()
private var entityConfigurationsMapping = [String: Set<String>]()
private var entityConfigurationsMapping = [String: Set<String>]() // TODO: change key to AnyEntity
deinit {

View File

@@ -8,6 +8,7 @@
import CoreGraphics
import Foundation
import ObjectiveC
public protocol ManagedObjectProtocol: class {}
@@ -17,7 +18,7 @@ public protocol EntityProtocol {
var entityDescription: NSEntityDescription { get }
}
protocol AttributeProtocol: class {
internal protocol AttributeProtocol: class {
static var attributeType: NSAttributeType { get }
var keyPath: String { get }
@@ -27,8 +28,8 @@ protocol AttributeProtocol: class {
open class CoreStoreManagedObject: ManagedObjectProtocol {
let rawObject: NSManagedObject?
let isMeta: Bool
internal let rawObject: NSManagedObject?
internal let isMeta: Bool
public required init(_ object: NSManagedObject?) {
@@ -59,12 +60,42 @@ open class CoreStoreManagedObject: ManagedObjectProtocol {
public struct Entity<O: CoreStoreManagedObject>: EntityProtocol {
public let entityDescription: NSEntityDescription
internal var dynamicClass: AnyClass {
return NSClassFromString(self.entityDescription.managedObjectClassName!)!
}
public init(_ entityName: String) {
let dynamicClassName = String(reflecting: O.self)
.appending("__\(entityName)")
.replacingOccurrences(of: ".", with: "_")
.replacingOccurrences(of: "<", with: "_")
.replacingOccurrences(of: ">", with: "_")
// TODO: assign entityName through ModelVersion and
// TODO: set NSEntityDescription.userInfo AnyEntity
let newClass: AnyClass?
if NSClassFromString(dynamicClassName) == nil {
newClass = objc_allocateClassPair(NSManagedObject.self, dynamicClassName, 0)
}
else {
newClass = nil
}
defer {
if let newClass = newClass {
objc_registerClassPair(newClass)
}
}
let entityDescription = NSEntityDescription()
entityDescription.name = entityName
entityDescription.managedObjectClassName = NSStringFromClass(NSManagedObject.self)
entityDescription.managedObjectClassName = dynamicClassName // TODO: return to NSManagedObject
entityDescription.properties = type(of: self).initializeAttributes(Mirror(reflecting: O.meta))
self.entityDescription = entityDescription
@@ -168,7 +199,7 @@ public extension ManagedObjectProtocol where Self: CoreStoreManagedObject {
public typealias Attribute = AttributeContainer<Self>
static var meta: Self {
internal static var meta: Self {
return self.init(nil)
}
@@ -250,16 +281,44 @@ public extension AttributeContainer.Optional where V: CVarArg {
}
}
protocol ModelVersionProtocol: class {
public final class ModelVersion {
static var version: String { get }
static var entities: [EntityProtocol] { get }
}
extension ModelVersionProtocol {
public let version: String
internal let entities: Set<NSEntityDescription>
internal let entityConfigurations: [String: Set<NSEntityDescription>]
static func entity<O: CoreStoreManagedObject>(for type: O.Type) -> Entity<O> {
public convenience init(version: String, entities: [EntityProtocol]) {
return self.entities.first(where: { $0 is Entity<O> })! as! Entity<O>
self.init(version: version, configurationEntities: [Into.defaultConfigurationName: entities])
}
public required init(version: String, configurationEntities: [String: [EntityProtocol]]) {
self.version = version
var entityConfigurations: [String: Set<NSEntityDescription>] = [:]
for (configuration, entities) in configurationEntities {
entityConfigurations[configuration] = Set(entities.map({ $0.entityDescription }))
}
let allEntities = Set(entityConfigurations.map({ $0.value }).joined())
entityConfigurations[Into.defaultConfigurationName] = allEntities
self.entityConfigurations = entityConfigurations
self.entities = allEntities
}
internal func createModel() -> NSManagedObjectModel {
let model = NSManagedObjectModel()
model.entities = self.entities.sorted(by: { $0.name! < $1.name! })
for (configuration, entities) in self.entityConfigurations {
model.setEntities(
entities.sorted(by: { $0.name! < $1.name! }),
forConfigurationName: configuration
)
}
return model
}
}