Implement dynamic initializers for Field properties (fixes #382)

This commit is contained in:
John Estropia
2020-05-23 12:07:16 +09:00
parent a7568eebdb
commit 56d0ea46ea
15 changed files with 455 additions and 142 deletions

View File

@@ -146,8 +146,7 @@ final class CollectionViewDemoViewController: UICollectionViewController {
ColorsDemo.stack.perform( ColorsDemo.stack.perform(
asynchronous: { (transaction) in asynchronous: { (transaction) in
let palette = transaction.create(Into<Palette>()) _ = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
}, },
completion: { _ in } completion: { _ in }
) )
@@ -159,8 +158,8 @@ final class CollectionViewDemoViewController: UICollectionViewController {
for palette in try transaction.fetchAll(From<Palette>()) { for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue .= Palette.randomHue() palette.hue = Palette.randomHue()
palette.colorName .= nil palette.colorName = nil
} }
}, },
completion: { _ in } completion: { _ in }

View File

@@ -35,8 +35,8 @@ struct ColorsDemo {
switch self { switch self {
case .all: return .init() case .all: return .init()
case .light: return (\Palette.brightness >= 0.9) case .light: return (\Palette.$brightness >= 0.9)
case .dark: return (\Palette.brightness <= 0.4) case .dark: return (\Palette.$brightness <= 0.4)
} }
} }
} }
@@ -47,9 +47,9 @@ struct ColorsDemo {
try! self.palettes.refetch( try! self.palettes.refetch(
From<Palette>() From<Palette>()
.sectionBy(\.colorName) .sectionBy(\.$colorName)
.where(self.filter.whereClause()) .where(self.filter.whereClause())
.orderBy(.ascending(\.hue)) .orderBy(.ascending(\.$hue))
) )
} }
} }
@@ -81,8 +81,8 @@ struct ColorsDemo {
return ColorsDemo.stack.publishList( return ColorsDemo.stack.publishList(
From<Palette>() From<Palette>()
.sectionBy(\.colorName) .sectionBy(\.$colorName)
.orderBy(.ascending(\.hue)) .orderBy(.ascending(\.$hue))
) )
}() }()
} }

View File

@@ -158,8 +158,7 @@ final class ListObserverDemoViewController: UITableViewController {
ColorsDemo.stack.perform( ColorsDemo.stack.perform(
asynchronous: { (transaction) in asynchronous: { (transaction) in
let palette = transaction.create(Into<Palette>()) _ = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
}, },
completion: { _ in } completion: { _ in }
) )
@@ -171,8 +170,8 @@ final class ListObserverDemoViewController: UITableViewController {
for palette in try transaction.fetchAll(From<Palette>()) { for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue .= Palette.randomHue() palette.hue = Palette.randomHue()
palette.colorName .= nil palette.colorName = nil
} }
}, },
completion: { _ in } completion: { _ in }

View File

@@ -43,7 +43,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
required init?(coder aDecoder: NSCoder) { required init?(coder aDecoder: NSCoder) {
if let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.hue))) { if let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.$hue))) {
self.monitor = ColorsDemo.stack.monitorObject(palette) self.monitor = ColorsDemo.stack.monitorObject(palette)
} }
@@ -52,12 +52,11 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
_ = try? ColorsDemo.stack.perform( _ = try? ColorsDemo.stack.perform(
synchronous: { (transaction) in synchronous: { (transaction) in
let palette = transaction.create(Into<Palette>()) _ = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
} }
) )
let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.hue)))! let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.$hue)))!
self.monitor = ColorsDemo.stack.monitorObject(palette) self.monitor = ColorsDemo.stack.monitorObject(palette)
} }
@@ -119,7 +118,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
if let palette = transaction.edit(self?.monitor?.object) { if let palette = transaction.edit(self?.monitor?.object) {
palette.hue .= Int(hue) palette.hue = Int(hue)
} }
}, },
completion: { _ in } completion: { _ in }
@@ -134,7 +133,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
if let palette = transaction.edit(self?.monitor?.object) { if let palette = transaction.edit(self?.monitor?.object) {
palette.saturation .= saturation palette.saturation = saturation
} }
}, },
completion: { _ in } completion: { _ in }
@@ -149,7 +148,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
if let palette = transaction.edit(self?.monitor?.object) { if let palette = transaction.edit(self?.monitor?.object) {
palette.brightness .= brightness palette.brightness = brightness
} }
}, },
completion: { _ in } completion: { _ in }
@@ -169,7 +168,7 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) { func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
self.colorNameLabel?.text = palette.colorName.value self.colorNameLabel?.text = palette.colorName
let color = palette.color let color = palette.color
self.colorNameLabel?.textColor = color self.colorNameLabel?.textColor = color
@@ -177,17 +176,17 @@ class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
self.hsbLabel?.text = palette.colorText self.hsbLabel?.text = palette.colorText
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.hue)) == true { if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$hue)) == true {
self.hueSlider?.value = Float(palette.hue.value) self.hueSlider?.value = Float(palette.hue)
} }
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.saturation)) == true { if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$saturation)) == true {
self.saturationSlider?.value = palette.saturation.value self.saturationSlider?.value = palette.saturation
} }
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.brightness)) == true { if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$brightness)) == true {
self.brightnessSlider?.value = palette.brightness.value self.brightnessSlider?.value = palette.brightness
} }
} }
} }

View File

@@ -16,31 +16,29 @@ import CoreStore
final class Palette: CoreStoreObject { final class Palette: CoreStoreObject {
let hue = Value.Required<Int>("hue", initial: 0) @Field.Stored(
let saturation = Value.Required<Float>("saturation", initial: 0) "hue",
let brightness = Value.Required<Float>("brightness", initial: 0) dynamicInitialValue: { Palette.randomHue() }
let colorName = Value.Optional<String>(
"colorName",
isTransient: true,
customGetter: Palette.getColorName
) )
var hue: Int
static func randomHue() -> Int { @Field.Stored("saturation")
var saturation: Float = 1
return Int(arc4random_uniform(360)) @Field.Stored(
} "brightness",
dynamicInitialValue: { Palette.randomBrightness() }
private static func getColorName(_ partialObject: PartialObject<Palette>) -> String? { )
var brightness: Float
if let colorName = partialObject.primitiveValue(for: { $0.colorName }) {
@Field.Virtual(
"colorName",
customGetter: { object, field in
if let colorName = field.primitiveValue {
return colorName return colorName
} }
let colorName: String let colorName: String
switch partialObject.value(for: { $0.hue }) % 360 { switch object.$hue.value % 360 {
case 0 ..< 20: colorName = "Lower Reds" case 0 ..< 20: colorName = "Lower Reds"
case 20 ..< 57: colorName = "Oranges and Browns" case 20 ..< 57: colorName = "Oranges and Browns"
case 57 ..< 90: colorName = "Yellow-Greens" case 57 ..< 90: colorName = "Yellow-Greens"
@@ -51,10 +49,21 @@ final class Palette: CoreStoreObject {
case 297 ..< 331: colorName = "Magentas" case 297 ..< 331: colorName = "Magentas"
default: colorName = "Upper Reds" default: colorName = "Upper Reds"
} }
field.primitiveValue = colorName
partialObject.setPrimitiveValue(colorName, for: { $0.colorName })
return colorName return colorName
} }
)
var colorName: String!
static func randomHue() -> Int {
return Int.random(in: 0 ..< 360)
}
static func randomBrightness() -> Float {
return (Float.random(in: 0 ..< 70) + 30) / 100.0
}
} }
extension Palette { extension Palette {
@@ -62,25 +71,15 @@ extension Palette {
var color: UIColor { var color: UIColor {
return UIColor( return UIColor(
hue: CGFloat(self.hue.value) / 360.0, hue: CGFloat(self.hue) / 360.0,
saturation: CGFloat(self.saturation.value), saturation: CGFloat(self.saturation),
brightness: CGFloat(self.brightness.value), brightness: CGFloat(self.brightness),
alpha: 1.0 alpha: 1.0
) )
} }
var colorText: String { var colorText: String {
return "H: \(self.hue.value)˚, S: \(round(self.saturation.value * 100.0))%, B: \(round(self.brightness.value * 100.0))%" return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%"
}
}
extension Palette {
func setInitialValues(in transaction: BaseDataTransaction) {
self.hue .= Palette.randomHue()
self.saturation .= Float(1.0)
self.brightness .= Float(arc4random_uniform(70) + 30) / 100.0
} }
} }

View File

@@ -33,8 +33,8 @@ final class SwiftUIContainerViewController: UIViewController {
rootView: SwiftUIView( rootView: SwiftUIView(
palettes: ColorsDemo.stack.publishList( palettes: ColorsDemo.stack.publishList(
From<Palette>() From<Palette>()
.sectionBy(\.colorName) .sectionBy(\.$colorName)
.orderBy(.ascending(\.hue)) .orderBy(.ascending(\.$hue))
) )
) )
.environment(\.dataStack, ColorsDemo.stack) .environment(\.dataStack, ColorsDemo.stack)

View File

@@ -61,8 +61,8 @@ struct SwiftUIView: View {
for palette in try transaction.fetchAll(From<Palette>()) { for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue .= Palette.randomHue() palette.hue = Palette.randomHue()
palette.colorName .= nil palette.colorName = nil
} }
}, },
completion: { _ in } completion: { _ in }
@@ -79,8 +79,7 @@ struct SwiftUIView: View {
self.dataStack.perform( self.dataStack.perform(
asynchronous: { transaction in asynchronous: { transaction in
let palette = transaction.create(Into<Palette>()) _ = transaction.create(Into<Palette>())
palette.setInitialValues(in: transaction)
}, },
completion: { _ in } completion: { _ in }
) )
@@ -173,8 +172,8 @@ struct SwiftUIView_Previews: PreviewProvider {
SwiftUIView( SwiftUIView(
palettes: ColorsDemo.stack.publishList( palettes: ColorsDemo.stack.publishList(
From<Palette>() From<Palette>()
.sectionBy(\.colorName) .sectionBy(\.$colorName)
.orderBy(.ascending(\.hue)) .orderBy(.ascending(\.$hue))
) )
) )
.environment(\.dataStack, ColorsDemo.stack) .environment(\.dataStack, ColorsDemo.stack)

View File

@@ -33,6 +33,7 @@ import Foundation
internal typealias CustomGetter = @convention(block) (_ rawObject: Any) -> Any? internal typealias CustomGetter = @convention(block) (_ rawObject: Any) -> Any?
internal typealias CustomSetter = @convention(block) (_ rawObject: Any, _ newValue: Any?) -> Void internal typealias CustomSetter = @convention(block) (_ rawObject: Any, _ newValue: Any?) -> Void
internal typealias CustomInitializer = @convention(block) (_ rawObject: Any) -> Void
internal typealias CustomGetterSetter = (getter: CustomGetter?, setter: CustomSetter?) internal typealias CustomGetterSetter = (getter: CustomGetter?, setter: CustomSetter?)
@nonobjc @inline(__always) @nonobjc @inline(__always)

View File

@@ -209,15 +209,17 @@ public final class CoreStoreSchema: DynamicSchema {
let rawModel = NSManagedObjectModel() let rawModel = NSManagedObjectModel()
var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:] var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
var allCustomGettersSetters: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]] = [:] var allCustomGettersSetters: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]] = [:]
var allCustomInitializers: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomInitializer]] = [:]
var allFieldCoders: [DynamicEntity: [KeyPathString: Internals.AnyFieldCoder]] = [:] var allFieldCoders: [DynamicEntity: [KeyPathString: Internals.AnyFieldCoder]] = [:]
for entity in self.allEntities { for entity in self.allEntities {
let (entityDescription, customGetterSetterByKeyPaths, fieldCoders) = self.entityDescription( let (entityDescription, customGetterSetterByKeyPaths, customInitializerByKeyPaths, fieldCoders) = self.entityDescription(
for: entity, for: entity,
initializer: CoreStoreSchema.firstPassCreateEntityDescription(from:in:) initializer: CoreStoreSchema.firstPassCreateEntityDescription(from:in:)
) )
entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription) entityDescriptionsByEntity[entity] = (entityDescription.copy() as! NSEntityDescription)
allCustomGettersSetters[entity] = customGetterSetterByKeyPaths allCustomGettersSetters[entity] = customGetterSetterByKeyPaths
allCustomInitializers[entity] = customInitializerByKeyPaths
allFieldCoders[entity] = fieldCoders allFieldCoders[entity] = fieldCoders
} }
CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity) CoreStoreSchema.secondPassConnectRelationshipAttributes(for: entityDescriptionsByEntity)
@@ -225,6 +227,7 @@ public final class CoreStoreSchema: DynamicSchema {
CoreStoreSchema.fourthPassSynthesizeManagedObjectClasses( CoreStoreSchema.fourthPassSynthesizeManagedObjectClasses(
for: entityDescriptionsByEntity, for: entityDescriptionsByEntity,
allCustomGettersSetters: allCustomGettersSetters, allCustomGettersSetters: allCustomGettersSetters,
allCustomInitializers: allCustomInitializers,
allFieldCoders: allFieldCoders allFieldCoders: allFieldCoders
) )
@@ -257,6 +260,7 @@ public final class CoreStoreSchema: DynamicSchema {
private var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:] private var entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription] = [:]
private var customGettersSettersByEntity: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]] = [:] private var customGettersSettersByEntity: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]] = [:]
private var customInitializersByEntity: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomInitializer]] = [:]
private var fieldCodersByEntity: [DynamicEntity: [KeyPathString: Internals.AnyFieldCoder]] = [:] private var fieldCodersByEntity: [DynamicEntity: [KeyPathString: Internals.AnyFieldCoder]] = [:]
private weak var cachedRawModel: NSManagedObjectModel? private weak var cachedRawModel: NSManagedObjectModel?
@@ -265,11 +269,13 @@ public final class CoreStoreSchema: DynamicSchema {
initializer: (DynamicEntity, ModelVersion) -> ( initializer: (DynamicEntity, ModelVersion) -> (
entity: NSEntityDescription, entity: NSEntityDescription,
customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter], customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter],
customInitializersByEntity: [KeyPathString: CoreStoreManagedObject.CustomInitializer],
fieldCoders: [KeyPathString: Internals.AnyFieldCoder] fieldCoders: [KeyPathString: Internals.AnyFieldCoder]
) )
) -> ( ) -> (
entity: NSEntityDescription, entity: NSEntityDescription,
customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter], customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter],
customInitializerByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomInitializer],
fieldCoders: [KeyPathString: Internals.AnyFieldCoder] fieldCoders: [KeyPathString: Internals.AnyFieldCoder]
) { ) {
@@ -278,23 +284,31 @@ public final class CoreStoreSchema: DynamicSchema {
return ( return (
cachedEntityDescription, cachedEntityDescription,
self.customGettersSettersByEntity[entity] ?? [:], self.customGettersSettersByEntity[entity] ?? [:],
self.customInitializersByEntity[entity] ?? [:],
self.fieldCodersByEntity[entity] ?? [:] self.fieldCodersByEntity[entity] ?? [:]
) )
} }
let modelVersion = self.modelVersion let modelVersion = self.modelVersion
let (entityDescription, customGetterSetterByKeyPaths, fieldCoders) = withoutActuallyEscaping( let (entityDescription, customGetterSetterByKeyPaths, customInitializerByKeyPaths, fieldCoders) = withoutActuallyEscaping(
initializer, initializer,
do: { $0(entity, modelVersion) } do: { $0(entity, modelVersion) }
) )
self.entityDescriptionsByEntity[entity] = entityDescription self.entityDescriptionsByEntity[entity] = entityDescription
self.customGettersSettersByEntity[entity] = customGetterSetterByKeyPaths self.customGettersSettersByEntity[entity] = customGetterSetterByKeyPaths
self.customInitializersByEntity[entity] = customInitializerByKeyPaths
self.fieldCodersByEntity[entity] = fieldCoders self.fieldCodersByEntity[entity] = fieldCoders
return (entityDescription, customGetterSetterByKeyPaths, fieldCoders) return (
entityDescription,
customGetterSetterByKeyPaths,
customInitializerByKeyPaths,
fieldCoders
)
} }
private static func firstPassCreateEntityDescription(from entity: DynamicEntity, in modelVersion: ModelVersion) -> ( private static func firstPassCreateEntityDescription(from entity: DynamicEntity, in modelVersion: ModelVersion) -> (
entity: NSEntityDescription, entity: NSEntityDescription,
customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter], customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter],
customInitializerByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomInitializer],
fieldCoders: [KeyPathString: Internals.AnyFieldCoder] fieldCoders: [KeyPathString: Internals.AnyFieldCoder]
) { ) {
@@ -306,6 +320,7 @@ public final class CoreStoreSchema: DynamicSchema {
entityDescription.managedObjectClassName = CoreStoreManagedObject.cs_subclassName(for: entity, in: modelVersion) entityDescription.managedObjectClassName = CoreStoreManagedObject.cs_subclassName(for: entity, in: modelVersion)
var keyPathsByAffectedKeyPaths: [KeyPathString: Set<KeyPathString>] = [:] var keyPathsByAffectedKeyPaths: [KeyPathString: Set<KeyPathString>] = [:]
var customInitialValuesByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomInitializer] = [:]
var customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter] = [:] var customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter] = [:]
var fieldCoders: [KeyPathString: Internals.AnyFieldCoder] = [:] var fieldCoders: [KeyPathString: Internals.AnyFieldCoder] = [:]
func createProperties(for type: CoreStoreObject.Type) -> [NSPropertyDescription] { func createProperties(for type: CoreStoreObject.Type) -> [NSPropertyDescription] {
@@ -338,6 +353,7 @@ public final class CoreStoreSchema: DynamicSchema {
keyPathsByAffectedKeyPaths[attribute.keyPath] = entityDescriptionValues.affectedByKeyPaths keyPathsByAffectedKeyPaths[attribute.keyPath] = entityDescriptionValues.affectedByKeyPaths
customGetterSetterByKeyPaths[attribute.keyPath] = (attribute.getter, attribute.setter) customGetterSetterByKeyPaths[attribute.keyPath] = (attribute.getter, attribute.setter)
customInitialValuesByKeyPaths[attribute.keyPath] = attribute.initializer
fieldCoders[attribute.keyPath] = valueTransformer fieldCoders[attribute.keyPath] = valueTransformer
case let relationship as FieldRelationshipProtocol: case let relationship as FieldRelationshipProtocol:
@@ -401,7 +417,12 @@ public final class CoreStoreSchema: DynamicSchema {
} }
entityDescription.properties = createProperties(for: entity.type as! CoreStoreObject.Type) entityDescription.properties = createProperties(for: entity.type as! CoreStoreObject.Type)
entityDescription.keyPathsByAffectedKeyPaths = keyPathsByAffectedKeyPaths entityDescription.keyPathsByAffectedKeyPaths = keyPathsByAffectedKeyPaths
return (entityDescription, customGetterSetterByKeyPaths, fieldCoders) return (
entityDescription,
customGetterSetterByKeyPaths,
customInitialValuesByKeyPaths,
fieldCoders
)
} }
private static func secondPassConnectRelationshipAttributes(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]) { private static func secondPassConnectRelationshipAttributes(for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription]) {
@@ -597,10 +618,15 @@ public final class CoreStoreSchema: DynamicSchema {
private static func fourthPassSynthesizeManagedObjectClasses( private static func fourthPassSynthesizeManagedObjectClasses(
for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription], for entityDescriptionsByEntity: [DynamicEntity: NSEntityDescription],
allCustomGettersSetters: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]], allCustomGettersSetters: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]],
allCustomInitializers: [DynamicEntity: [KeyPathString: CoreStoreManagedObject.CustomInitializer]],
allFieldCoders: [DynamicEntity: [KeyPathString: Internals.AnyFieldCoder]] allFieldCoders: [DynamicEntity: [KeyPathString: Internals.AnyFieldCoder]]
) { ) {
func createManagedObjectSubclass(for entityDescription: NSEntityDescription, customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]?) { func createManagedObjectSubclass(
for entityDescription: NSEntityDescription,
customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]?,
customInitializers: [KeyPathString: CoreStoreManagedObject.CustomInitializer]?
) {
let superEntity = entityDescription.superentity let superEntity = entityDescription.superentity
let className = entityDescription.managedObjectClassName! let className = entityDescription.managedObjectClassName!
@@ -612,7 +638,8 @@ public final class CoreStoreSchema: DynamicSchema {
createManagedObjectSubclass( createManagedObjectSubclass(
for: superEntity, for: superEntity,
customGetterSetterByKeyPaths: superEntity.coreStoreEntity.flatMap({ allCustomGettersSetters[$0] }) customGetterSetterByKeyPaths: superEntity.coreStoreEntity.flatMap({ allCustomGettersSetters[$0] }),
customInitializers: superEntity.coreStoreEntity.flatMap({ allCustomInitializers[$0] })
) )
} }
let superClass = Internals.with { () -> CoreStoreManagedObject.Type in let superClass = Internals.with { () -> CoreStoreManagedObject.Type in
@@ -675,6 +702,7 @@ public final class CoreStoreSchema: DynamicSchema {
} }
} }
} }
swizzle_keyPathsForValuesAffectingValueForKey: do {
let newSelector = NSSelectorFromString("cs_keyPathsForValuesAffectingValueForKey:") let newSelector = NSSelectorFromString("cs_keyPathsForValuesAffectingValueForKey:")
let keyPathsByAffectedKeyPaths = entityDescription.keyPathsByAffectedKeyPaths let keyPathsByAffectedKeyPaths = entityDescription.keyPathsByAffectedKeyPaths
@@ -704,11 +732,50 @@ public final class CoreStoreSchema: DynamicSchema {
method_exchangeImplementations(origMethod, newMethod) method_exchangeImplementations(origMethod, newMethod)
} }
} }
swizzle_awakeFromInsert: do {
let newSelector = NSSelectorFromString("cs_awakeFromInsert")
let awakeFromInsertValue: @convention(block) (Any) -> Void
if let customInitializers = customInitializers,
!customInitializers.isEmpty {
let initializers = Array(customInitializers.values)
awakeFromInsertValue = { (instance) in
initializers.forEach {
$0(instance)
}
}
}
else {
awakeFromInsertValue = { _ in }
}
let origSelector = #selector(CoreStoreManagedObject.awakeFromInsert)
let origMethod = class_getInstanceMethod(managedObjectClass, origSelector)!
let origImp = method_getImplementation(origMethod)
let newImp = imp_implementationWithBlock(awakeFromInsertValue)
if class_addMethod(managedObjectClass, origSelector, newImp, method_getTypeEncoding(origMethod)) {
class_replaceMethod(managedObjectClass, newSelector, origImp, method_getTypeEncoding(origMethod))
}
else {
let newMethod = class_getInstanceMethod(managedObjectClass, newSelector)!
method_exchangeImplementations(origMethod, newMethod)
}
}
}
for (dynamicEntity, entityDescription) in entityDescriptionsByEntity { for (dynamicEntity, entityDescription) in entityDescriptionsByEntity {
createManagedObjectSubclass( createManagedObjectSubclass(
for: entityDescription, for: entityDescription,
customGetterSetterByKeyPaths: allCustomGettersSetters[dynamicEntity] customGetterSetterByKeyPaths: allCustomGettersSetters[dynamicEntity],
customInitializers: allCustomInitializers[dynamicEntity]
) )
} }

View File

@@ -94,6 +94,32 @@ extension FieldContainer {
valueTransformer: { Internals.AnyFieldCoder(fieldCoderType) }, valueTransformer: { Internals.AnyFieldCoder(fieldCoderType) },
customGetter: customGetter, customGetter: customGetter,
customSetter: customSetter, customSetter: customSetter,
dynamicInitialValue: nil,
affectedByKeyPaths: affectedByKeyPaths
)
}
public init<Coder: FieldCoderType>(
_ keyPath: KeyPathString,
versionHashModifier: @autoclosure @escaping () -> String? = nil,
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
coder fieldCoderType: Coder.Type,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
dynamicInitialValue: @escaping () -> V
) where Coder.FieldStoredValue == V {
self.init(
defaultValue: nil,
keyPath: keyPath,
isOptional: false,
versionHashModifier: versionHashModifier,
renamingIdentifier: previousVersionKeyPath,
valueTransformer: { Internals.AnyFieldCoder(fieldCoderType) },
customGetter: customGetter,
customSetter: customSetter,
dynamicInitialValue: dynamicInitialValue,
affectedByKeyPaths: affectedByKeyPaths affectedByKeyPaths: affectedByKeyPaths
) )
} }
@@ -142,6 +168,32 @@ extension FieldContainer {
valueTransformer: { Internals.AnyFieldCoder(tag: UUID(), encode: coder.encode, decode: coder.decode) }, valueTransformer: { Internals.AnyFieldCoder(tag: UUID(), encode: coder.encode, decode: coder.decode) },
customGetter: customGetter, customGetter: customGetter,
customSetter: customSetter, customSetter: customSetter,
dynamicInitialValue: nil,
affectedByKeyPaths: affectedByKeyPaths
)
}
public init(
_ keyPath: KeyPathString,
versionHashModifier: @autoclosure @escaping () -> String? = nil,
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
coder: (encode: (V) -> Data?, decode: (Data?) -> V),
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
dynamicInitialValue: @escaping () -> V
) {
self.init(
defaultValue: nil,
keyPath: keyPath,
isOptional: false,
versionHashModifier: versionHashModifier,
renamingIdentifier: previousVersionKeyPath,
valueTransformer: { Internals.AnyFieldCoder(tag: UUID(), encode: coder.encode, decode: coder.decode) },
customGetter: customGetter,
customSetter: customSetter,
dynamicInitialValue: dynamicInitialValue,
affectedByKeyPaths: affectedByKeyPaths affectedByKeyPaths: affectedByKeyPaths
) )
} }
@@ -334,11 +386,28 @@ extension FieldContainer {
} }
} }
internal var initializer: CoreStoreManagedObject.CustomInitializer? {
guard let dynamicInitialValue = self.dynamicInitialValue else {
return nil
}
let keyPath = self.keyPath
return { (_ id: Any) -> Void in
let rawObject = id as! CoreStoreManagedObject
rawObject.setPrimitiveValue(
dynamicInitialValue(),
forKey: keyPath
)
}
}
// MARK: FilePrivate // MARK: FilePrivate
fileprivate init( fileprivate init(
defaultValue: @escaping () -> Any?, defaultValue: (() -> Any?)?,
keyPath: KeyPathString, keyPath: KeyPathString,
isOptional: Bool, isOptional: Bool,
versionHashModifier: @escaping () -> String?, versionHashModifier: @escaping () -> String?,
@@ -346,6 +415,7 @@ extension FieldContainer {
valueTransformer: @escaping () -> Internals.AnyFieldCoder?, valueTransformer: @escaping () -> Internals.AnyFieldCoder?,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?, customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? , customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? ,
dynamicInitialValue: (() -> V)?,
affectedByKeyPaths: @escaping () -> Set<KeyPathString>) { affectedByKeyPaths: @escaping () -> Set<KeyPathString>) {
self.keyPath = keyPath self.keyPath = keyPath
@@ -361,14 +431,17 @@ extension FieldContainer {
renamingIdentifier: renamingIdentifier(), renamingIdentifier: renamingIdentifier(),
valueTransformer: fieldCoder, valueTransformer: fieldCoder,
affectedByKeyPaths: affectedByKeyPaths(), affectedByKeyPaths: affectedByKeyPaths(),
defaultValue: Internals.AnyFieldCoder.TransformableDefaultValueCodingBox( defaultValue: defaultValue.map {
defaultValue: defaultValue(), Internals.AnyFieldCoder.TransformableDefaultValueCodingBox(
defaultValue: $0(),
fieldCoder: fieldCoder fieldCoder: fieldCoder
) ) as Any
}
) )
} }
self.customGetter = customGetter self.customGetter = customGetter
self.customSetter = customSetter self.customSetter = customSetter
self.dynamicInitialValue = dynamicInitialValue
} }
@@ -376,6 +449,7 @@ extension FieldContainer {
private let customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? private let customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?
private let customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? private let customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)?
private let dynamicInitialValue: (() -> V)?
} }
} }
@@ -422,6 +496,32 @@ extension FieldContainer.Coded where V: FieldOptionalType {
valueTransformer: { Internals.AnyFieldCoder(coder) }, valueTransformer: { Internals.AnyFieldCoder(coder) },
customGetter: customGetter, customGetter: customGetter,
customSetter: customSetter, customSetter: customSetter,
dynamicInitialValue: nil,
affectedByKeyPaths: affectedByKeyPaths
)
}
public init<Coder: FieldCoderType>(
_ keyPath: KeyPathString,
versionHashModifier: @autoclosure @escaping () -> String? = nil,
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
coder: Coder.Type,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
dynamicInitialValue: @escaping () -> V
) where Coder.FieldStoredValue == V.Wrapped {
self.init(
defaultValue: nil,
keyPath: keyPath,
isOptional: true,
versionHashModifier: versionHashModifier,
renamingIdentifier: previousVersionKeyPath,
valueTransformer: { Internals.AnyFieldCoder(coder) },
customGetter: customGetter,
customSetter: customSetter,
dynamicInitialValue: dynamicInitialValue,
affectedByKeyPaths: affectedByKeyPaths affectedByKeyPaths: affectedByKeyPaths
) )
} }
@@ -470,6 +570,32 @@ extension FieldContainer.Coded where V: FieldOptionalType {
valueTransformer: { Internals.AnyFieldCoder(tag: UUID(), encode: coder.encode, decode: coder.decode) }, valueTransformer: { Internals.AnyFieldCoder(tag: UUID(), encode: coder.encode, decode: coder.decode) },
customGetter: customGetter, customGetter: customGetter,
customSetter: customSetter, customSetter: customSetter,
dynamicInitialValue: nil,
affectedByKeyPaths: affectedByKeyPaths
)
}
public init(
_ keyPath: KeyPathString,
versionHashModifier: @autoclosure @escaping () -> String? = nil,
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
coder: (encode: (V) -> Data?, decode: (Data?) -> V),
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
dynamicInitialValue: @escaping () -> V
) {
self.init(
defaultValue: nil,
keyPath: keyPath,
isOptional: true,
versionHashModifier: versionHashModifier,
renamingIdentifier: previousVersionKeyPath,
valueTransformer: { Internals.AnyFieldCoder(tag: UUID(), encode: coder.encode, decode: coder.decode) },
customGetter: customGetter,
customSetter: customSetter,
dynamicInitialValue: dynamicInitialValue,
affectedByKeyPaths: affectedByKeyPaths affectedByKeyPaths: affectedByKeyPaths
) )
} }
@@ -516,6 +642,31 @@ extension FieldContainer.Coded where V: DefaultNSSecureCodable {
valueTransformer: { Internals.AnyFieldCoder(FieldCoders.DefaultNSSecureCoding<V>.self) }, valueTransformer: { Internals.AnyFieldCoder(FieldCoders.DefaultNSSecureCoding<V>.self) },
customGetter: customGetter, customGetter: customGetter,
customSetter: customSetter, customSetter: customSetter,
dynamicInitialValue: nil,
affectedByKeyPaths: affectedByKeyPaths
)
}
public init(
_ keyPath: KeyPathString,
versionHashModifier: @autoclosure @escaping () -> String? = nil,
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
dynamicInitialValue: @escaping () -> V
) {
self.init(
defaultValue: nil,
keyPath: keyPath,
isOptional: false,
versionHashModifier: versionHashModifier,
renamingIdentifier: previousVersionKeyPath,
valueTransformer: { Internals.AnyFieldCoder(FieldCoders.DefaultNSSecureCoding<V>.self) },
customGetter: customGetter,
customSetter: customSetter,
dynamicInitialValue: dynamicInitialValue,
affectedByKeyPaths: affectedByKeyPaths affectedByKeyPaths: affectedByKeyPaths
) )
} }
@@ -562,6 +713,31 @@ extension FieldContainer.Coded where V: FieldOptionalType, V.Wrapped: DefaultNSS
valueTransformer: { Internals.AnyFieldCoder(FieldCoders.DefaultNSSecureCoding<V.Wrapped>.self) }, valueTransformer: { Internals.AnyFieldCoder(FieldCoders.DefaultNSSecureCoding<V.Wrapped>.self) },
customGetter: customGetter, customGetter: customGetter,
customSetter: customSetter, customSetter: customSetter,
dynamicInitialValue: nil,
affectedByKeyPaths: affectedByKeyPaths
)
}
public init(
_ keyPath: KeyPathString,
versionHashModifier: @autoclosure @escaping () -> String? = nil,
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
dynamicInitialValue: @escaping () -> V
) {
self.init(
defaultValue: nil,
keyPath: keyPath,
isOptional: true,
versionHashModifier: versionHashModifier,
renamingIdentifier: previousVersionKeyPath,
valueTransformer: { Internals.AnyFieldCoder(FieldCoders.DefaultNSSecureCoding<V.Wrapped>.self) },
customGetter: customGetter,
customSetter: customSetter,
dynamicInitialValue: dynamicInitialValue,
affectedByKeyPaths: affectedByKeyPaths affectedByKeyPaths: affectedByKeyPaths
) )
} }

View File

@@ -85,6 +85,30 @@ extension FieldContainer {
renamingIdentifier: previousVersionKeyPath, renamingIdentifier: previousVersionKeyPath,
customGetter: customGetter, customGetter: customGetter,
customSetter: customSetter, customSetter: customSetter,
dynamicInitialValue: nil,
affectedByKeyPaths: affectedByKeyPaths
)
}
public init(
_ keyPath: KeyPathString,
versionHashModifier: @autoclosure @escaping () -> String? = nil,
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
dynamicInitialValue: @escaping () -> V
) {
self.init(
wrappedValue: nil,
keyPath: keyPath,
isOptional: false,
versionHashModifier: versionHashModifier,
renamingIdentifier: previousVersionKeyPath,
customGetter: customGetter,
customSetter: customSetter,
dynamicInitialValue: dynamicInitialValue,
affectedByKeyPaths: affectedByKeyPaths affectedByKeyPaths: affectedByKeyPaths
) )
} }
@@ -263,17 +287,35 @@ extension FieldContainer {
} }
} }
internal var initializer: CoreStoreManagedObject.CustomInitializer? {
guard let dynamicInitialValue = self.dynamicInitialValue else {
return nil
}
let keyPath = self.keyPath
return { (_ id: Any) -> Void in
let rawObject = id as! CoreStoreManagedObject
rawObject.setPrimitiveValue(
dynamicInitialValue().cs_toFieldStoredNativeType(),
forKey: keyPath
)
}
}
// MARK: FilePrivate // MARK: FilePrivate
fileprivate init( fileprivate init(
wrappedValue initial: @escaping () -> V, wrappedValue initial: (() -> V)?,
keyPath: KeyPathString, keyPath: KeyPathString,
isOptional: Bool, isOptional: Bool,
versionHashModifier: @escaping () -> String?, versionHashModifier: @escaping () -> String?,
renamingIdentifier: @escaping () -> String?, renamingIdentifier: @escaping () -> String?,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?, customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? , customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)?,
dynamicInitialValue: (() -> V)?,
affectedByKeyPaths: @escaping () -> Set<KeyPathString>) { affectedByKeyPaths: @escaping () -> Set<KeyPathString>) {
self.keyPath = keyPath self.keyPath = keyPath
@@ -287,11 +329,12 @@ extension FieldContainer {
renamingIdentifier: renamingIdentifier(), renamingIdentifier: renamingIdentifier(),
valueTransformer: nil, valueTransformer: nil,
affectedByKeyPaths: affectedByKeyPaths(), affectedByKeyPaths: affectedByKeyPaths(),
defaultValue: initial().cs_toFieldStoredNativeType() defaultValue: initial?().cs_toFieldStoredNativeType()
) )
} }
self.customGetter = customGetter self.customGetter = customGetter
self.customSetter = customSetter self.customSetter = customSetter
self.dynamicInitialValue = dynamicInitialValue
} }
@@ -299,6 +342,7 @@ extension FieldContainer {
private let customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? private let customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)?
private let customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? private let customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)?
private let dynamicInitialValue: (() -> V)?
} }
} }
@@ -331,7 +375,8 @@ extension FieldContainer.Stored where V: FieldOptionalType {
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil, previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil, customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil, customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []) { affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = []
) {
self.init( self.init(
wrappedValue: initial, wrappedValue: initial,
@@ -341,6 +386,30 @@ extension FieldContainer.Stored where V: FieldOptionalType {
renamingIdentifier: previousVersionKeyPath, renamingIdentifier: previousVersionKeyPath,
customGetter: customGetter, customGetter: customGetter,
customSetter: customSetter, customSetter: customSetter,
dynamicInitialValue: nil,
affectedByKeyPaths: affectedByKeyPaths
)
}
public init(
_ keyPath: KeyPathString,
versionHashModifier: @autoclosure @escaping () -> String? = nil,
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
customGetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>) -> V)? = nil,
customSetter: ((_ object: ObjectProxy<O>, _ field: ObjectProxy<O>.FieldProxy<V>, _ newValue: V) -> Void)? = nil,
affectedByKeyPaths: @autoclosure @escaping () -> Set<KeyPathString> = [],
dynamicInitialValue: @escaping () -> V
) {
self.init(
wrappedValue: nil,
keyPath: keyPath,
isOptional: true,
versionHashModifier: versionHashModifier,
renamingIdentifier: previousVersionKeyPath,
customGetter: customGetter,
customSetter: customSetter,
dynamicInitialValue: dynamicInitialValue,
affectedByKeyPaths: affectedByKeyPaths affectedByKeyPaths: affectedByKeyPaths
) )
} }

View File

@@ -276,6 +276,8 @@ extension FieldContainer {
} }
} }
let initializer: CoreStoreManagedObject.CustomInitializer? = nil
// MARK: FilePrivate // MARK: FilePrivate

View File

@@ -48,4 +48,5 @@ internal protocol FieldAttributeProtocol: FieldProtocol {
var entityDescriptionValues: () -> EntityDescriptionValues { get } var entityDescriptionValues: () -> EntityDescriptionValues { get }
var getter: CoreStoreManagedObject.CustomGetter? { get } var getter: CoreStoreManagedObject.CustomGetter? { get }
var setter: CoreStoreManagedObject.CustomSetter? { get } var setter: CoreStoreManagedObject.CustomSetter? { get }
var initializer: CoreStoreManagedObject.CustomInitializer? { get }
} }

View File

@@ -345,6 +345,30 @@ extension From where O: CoreStoreObject {
return self.select(R.self, [SelectTerm<O>.attribute(keyPath)]) return self.select(R.self, [SelectTerm<O>.attribute(keyPath)])
} }
/**
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections
- parameter sectionKeyPath: the `KeyPath` to use to group the objects into sections
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
*/
@available(macOS 10.12, *)
public func sectionBy<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Stored<T>>) -> SectionMonitorChainBuilder<O> {
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, { $0 })
}
/**
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections
- parameter sectionKeyPath: the `KeyPath` to use to group the objects into sections
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
*/
@available(macOS 10.12, *)
public func sectionBy<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Virtual<T>>) -> SectionMonitorChainBuilder<O> {
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, { $0 })
}
/** /**
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections

View File

@@ -115,27 +115,6 @@ extension NSEntityDescription {
} }
} }
@nonobjc
internal var customGetterSetterByKeyPaths: [KeyPathString: CoreStoreManagedObject.CustomGetterSetter] {
get {
if let userInfo = self.userInfo,
let value = userInfo[UserInfoKey.CoreStoreManagedObjectCustomGetterSetterByKeyPaths] {
return value as! [KeyPathString: CoreStoreManagedObject.CustomGetterSetter]
}
return [:]
}
set {
cs_setUserInfo { (userInfo) in
userInfo[UserInfoKey.CoreStoreManagedObjectCustomGetterSetterByKeyPaths] = newValue
}
}
}
// MARK: Private // MARK: Private
@@ -151,7 +130,6 @@ extension NSEntityDescription {
fileprivate static let CoreStoreManagedObjectUniqueConstraints = "CoreStoreManagedObjectUniqueConstraints" fileprivate static let CoreStoreManagedObjectUniqueConstraints = "CoreStoreManagedObjectUniqueConstraints"
fileprivate static let CoreStoreManagedObjectKeyPathsByAffectedKeyPaths = "CoreStoreManagedObjectKeyPathsByAffectedKeyPaths" fileprivate static let CoreStoreManagedObjectKeyPathsByAffectedKeyPaths = "CoreStoreManagedObjectKeyPathsByAffectedKeyPaths"
fileprivate static let CoreStoreManagedObjectCustomGetterSetterByKeyPaths = "CoreStoreManagedObjectCustomGetterSetterByKeyPaths"
} }