mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-15 05:33:31 +01:00
performant access of relationship objectIDs for snapshots
This commit is contained in:
@@ -172,13 +172,20 @@ extension CoreStoreObject {
|
||||
switch child.value {
|
||||
|
||||
case let property as FieldAttributeProtocol:
|
||||
Internals.assert(
|
||||
object.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(type(of: property).dynamicObjectType))'s value outside it's designated queue."
|
||||
)
|
||||
attributes[property.keyPath] = type(of: property).read(
|
||||
field: property,
|
||||
for: object.rawObject!,
|
||||
bypassThreadCheck: false
|
||||
for: object.rawObject!
|
||||
)
|
||||
|
||||
case let property as FieldRelationshipProtocol:
|
||||
Internals.assert(
|
||||
object.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(type(of: property).dynamicObjectType))'s value outside it's designated queue."
|
||||
)
|
||||
attributes[property.keyPath] = type(of: property).valueForSnapshot(
|
||||
field: property,
|
||||
for: object.rawObject!
|
||||
@@ -219,10 +226,23 @@ extension CoreStoreObject {
|
||||
switch property {
|
||||
|
||||
case let property as FieldAttributeProtocol:
|
||||
Internals.assert(
|
||||
object.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(type(of: property).dynamicObjectType))'s value outside it's designated queue."
|
||||
)
|
||||
values[property.keyPath] = type(of: property).read(
|
||||
field: property,
|
||||
for: rawObject,
|
||||
bypassThreadCheck: false
|
||||
for: rawObject
|
||||
)
|
||||
|
||||
case let property as FieldRelationshipProtocol:
|
||||
Internals.assert(
|
||||
object.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(type(of: property).dynamicObjectType))'s value outside it's designated queue."
|
||||
)
|
||||
values[property.keyPath] = type(of: property).valueForSnapshot(
|
||||
field: property,
|
||||
for: object.rawObject!
|
||||
)
|
||||
|
||||
default:
|
||||
|
||||
@@ -47,7 +47,7 @@ public protocol FieldRelationshipType {
|
||||
|
||||
static func cs_toSnapshotType(from value: PublishedType) -> SnapshotValueType
|
||||
|
||||
static func cs_valueForSnapshot(from value: NativeValueType?) -> SnapshotValueType
|
||||
static func cs_valueForSnapshot(from objectIDs: [DestinationObjectType.ObjectID]) -> SnapshotValueType
|
||||
}
|
||||
|
||||
public protocol FieldRelationshipToOneType: FieldRelationshipType {}
|
||||
@@ -88,9 +88,9 @@ extension Optional: FieldRelationshipType, FieldRelationshipToOneType where Wrap
|
||||
return value?.objectID()
|
||||
}
|
||||
|
||||
public static func cs_valueForSnapshot(from value: NativeValueType?) -> SnapshotValueType {
|
||||
public static func cs_valueForSnapshot(from objectIDs: [DestinationObjectType.ObjectID]) -> SnapshotValueType {
|
||||
|
||||
return value?.objectID
|
||||
return objectIDs.first
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,13 +129,9 @@ extension Array: FieldRelationshipType, FieldRelationshipToManyType, FieldRelati
|
||||
return value.map({ $0.objectID() })
|
||||
}
|
||||
|
||||
public static func cs_valueForSnapshot(from value: NativeValueType?) -> SnapshotValueType {
|
||||
public static func cs_valueForSnapshot(from objectIDs: [DestinationObjectType.ObjectID]) -> SnapshotValueType {
|
||||
|
||||
guard let value = value else {
|
||||
|
||||
return []
|
||||
}
|
||||
return value.map({ ($0 as! NSManagedObject).objectID })
|
||||
return objectIDs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,12 +169,8 @@ extension Set: FieldRelationshipType, FieldRelationshipToManyType, FieldRelation
|
||||
return SnapshotValueType(value.map({ $0.objectID() }))
|
||||
}
|
||||
|
||||
public static func cs_valueForSnapshot(from value: NativeValueType?) -> SnapshotValueType {
|
||||
public static func cs_valueForSnapshot(from objectIDs: [DestinationObjectType.ObjectID]) -> SnapshotValueType {
|
||||
|
||||
guard let value = value else {
|
||||
|
||||
return []
|
||||
}
|
||||
return .init(value.map({ ($0 as! NSManagedObject).objectID }))
|
||||
return .init(objectIDs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,11 @@ extension FieldContainer {
|
||||
instance.rawObject != nil,
|
||||
"Attempted to access values from a \(Internals.typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return self.read(field: instance[keyPath: storageKeyPath], for: instance.rawObject!, bypassThreadCheck: false) as! V
|
||||
Internals.assert(
|
||||
instance.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.read(field: instance[keyPath: storageKeyPath], for: instance.rawObject!) as! V
|
||||
}
|
||||
set {
|
||||
|
||||
@@ -169,6 +173,10 @@ extension FieldContainer {
|
||||
instance.rawObject != nil,
|
||||
"Attempted to access values from a \(Internals.typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
Internals.assert(
|
||||
instance.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.modify(field: instance[keyPath: storageKeyPath], for: instance.rawObject!, newValue: newValue)
|
||||
}
|
||||
}
|
||||
@@ -200,12 +208,13 @@ extension FieldContainer {
|
||||
|
||||
// MARK: FieldProtocol
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject, bypassThreadCheck: Bool) -> Any? {
|
||||
internal static var dynamicObjectType: CoreStoreObject.Type {
|
||||
|
||||
return ObjectType.self
|
||||
}
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
|
||||
Internals.assert(
|
||||
bypassThreadCheck || rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = field as! Self
|
||||
if let customGetter = field.customGetter {
|
||||
|
||||
@@ -227,10 +236,6 @@ extension FieldContainer {
|
||||
|
||||
internal static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?) {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
Internals.assert(
|
||||
rawObject.isEditableInContext() == true,
|
||||
"Attempted to update a \(Internals.typeName(O.self))'s value from outside a transaction."
|
||||
|
||||
@@ -99,7 +99,11 @@ extension FieldContainer {
|
||||
instance.rawObject != nil,
|
||||
"Attempted to access values from a \(Internals.typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return self.read(field: instance[keyPath: storageKeyPath], for: instance.rawObject!, bypassThreadCheck: false) as! V
|
||||
Internals.assert(
|
||||
instance.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.read(field: instance[keyPath: storageKeyPath], for: instance.rawObject!) as! V
|
||||
}
|
||||
set {
|
||||
|
||||
@@ -107,6 +111,10 @@ extension FieldContainer {
|
||||
instance.rawObject != nil,
|
||||
"Attempted to access values from a \(Internals.typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
Internals.assert(
|
||||
instance.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.modify(field: instance[keyPath: storageKeyPath], for: instance.rawObject!, newValue: newValue)
|
||||
}
|
||||
}
|
||||
@@ -138,12 +146,13 @@ extension FieldContainer {
|
||||
|
||||
// MARK: FieldProtocol
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject, bypassThreadCheck: Bool) -> Any? {
|
||||
internal static var dynamicObjectType: CoreStoreObject.Type {
|
||||
|
||||
return ObjectType.self
|
||||
}
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
|
||||
Internals.assert(
|
||||
bypassThreadCheck || rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = field as! Self
|
||||
let keyPath = field.keyPath
|
||||
return V.cs_toReturnType(
|
||||
@@ -152,11 +161,7 @@ extension FieldContainer {
|
||||
}
|
||||
|
||||
internal static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?) {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isEditableInContext() == true,
|
||||
"Attempted to update a \(Internals.typeName(O.self))'s value from outside a transaction."
|
||||
@@ -182,10 +187,7 @@ extension FieldContainer {
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = field as! Self
|
||||
let keyPath = field.keyPath
|
||||
return V.cs_valueForSnapshot(
|
||||
from: rawObject.value(forKey: keyPath) as! V.NativeValueType?
|
||||
)
|
||||
return V.cs_valueForSnapshot(from: rawObject.objectIDs(forRelationshipNamed: field.keyPath))
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -128,7 +128,11 @@ extension FieldContainer {
|
||||
instance.rawObject != nil,
|
||||
"Attempted to access values from a \(Internals.typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return self.read(field: instance[keyPath: storageKeyPath], for: instance.rawObject!, bypassThreadCheck: false) as! V
|
||||
Internals.assert(
|
||||
instance.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.read(field: instance[keyPath: storageKeyPath], for: instance.rawObject!) as! V
|
||||
}
|
||||
set {
|
||||
|
||||
@@ -136,6 +140,10 @@ extension FieldContainer {
|
||||
instance.rawObject != nil,
|
||||
"Attempted to access values from a \(Internals.typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
Internals.assert(
|
||||
instance.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.modify(field: instance[keyPath: storageKeyPath], for: instance.rawObject!, newValue: newValue)
|
||||
}
|
||||
}
|
||||
@@ -167,12 +175,13 @@ extension FieldContainer {
|
||||
|
||||
// MARK: FieldProtocol
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject, bypassThreadCheck: Bool) -> Any? {
|
||||
internal static var dynamicObjectType: CoreStoreObject.Type {
|
||||
|
||||
return ObjectType.self
|
||||
}
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
|
||||
Internals.assert(
|
||||
bypassThreadCheck || rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = field as! Self
|
||||
if let customGetter = field.customGetter {
|
||||
|
||||
@@ -194,10 +203,6 @@ extension FieldContainer {
|
||||
|
||||
internal static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?) {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
Internals.assert(
|
||||
rawObject.isEditableInContext() == true,
|
||||
"Attempted to update a \(Internals.typeName(O.self))'s value from outside a transaction."
|
||||
|
||||
@@ -139,7 +139,11 @@ extension FieldContainer {
|
||||
instance.rawObject != nil,
|
||||
"Attempted to access values from a \(Internals.typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
return self.read(field: instance[keyPath: storageKeyPath], for: instance.rawObject!, bypassThreadCheck: false) as! V
|
||||
Internals.assert(
|
||||
instance.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.read(field: instance[keyPath: storageKeyPath], for: instance.rawObject!) as! V
|
||||
}
|
||||
set {
|
||||
|
||||
@@ -147,6 +151,10 @@ extension FieldContainer {
|
||||
instance.rawObject != nil,
|
||||
"Attempted to access values from a \(Internals.typeName(O.self)) meta object. Meta objects are only used for querying keyPaths and infering types."
|
||||
)
|
||||
Internals.assert(
|
||||
instance.rawObject?.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
return self.modify(field: instance[keyPath: storageKeyPath], for: instance.rawObject!, newValue: newValue)
|
||||
}
|
||||
}
|
||||
@@ -178,12 +186,13 @@ extension FieldContainer {
|
||||
|
||||
// MARK: FieldProtocol
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject, bypassThreadCheck: Bool) -> Any? {
|
||||
internal static var dynamicObjectType: CoreStoreObject.Type {
|
||||
|
||||
return ObjectType.self
|
||||
}
|
||||
|
||||
internal static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any? {
|
||||
|
||||
Internals.assert(
|
||||
bypassThreadCheck || rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = field as! Self
|
||||
if let customGetter = field.customGetter {
|
||||
|
||||
@@ -205,10 +214,6 @@ extension FieldContainer {
|
||||
|
||||
internal static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?) {
|
||||
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
Internals.assert(
|
||||
rawObject.isEditableInContext() == true,
|
||||
"Attempted to update a \(Internals.typeName(O.self))'s value from outside a transaction."
|
||||
|
||||
@@ -43,6 +43,8 @@ internal protocol FieldAttributeProtocol: FieldProtocol {
|
||||
defaultValue: Any?
|
||||
)
|
||||
|
||||
static var dynamicObjectType: CoreStoreObject.Type { get }
|
||||
|
||||
var entityDescriptionValues: () -> EntityDescriptionValues { get }
|
||||
var getter: CoreStoreManagedObject.CustomGetter? { get }
|
||||
var setter: CoreStoreManagedObject.CustomSetter? { get }
|
||||
|
||||
@@ -30,7 +30,9 @@ import CoreData
|
||||
// MARK: - FieldProtocol
|
||||
|
||||
internal protocol FieldProtocol: PropertyProtocol {
|
||||
|
||||
static var dynamicObjectType: CoreStoreObject.Type { get }
|
||||
|
||||
static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject, bypassThreadCheck: Bool) -> Any?
|
||||
static func read(field: FieldProtocol, for rawObject: CoreStoreManagedObject) -> Any?
|
||||
static func modify(field: FieldProtocol, for rawObject: CoreStoreManagedObject, newValue: Any?)
|
||||
}
|
||||
|
||||
@@ -133,11 +133,7 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
let keyPathString = field.keyPath
|
||||
self.getValue = {
|
||||
|
||||
return type(of: field).read(
|
||||
field: field,
|
||||
for: rawObject,
|
||||
bypassThreadCheck: true // May be called from NSError logs
|
||||
) as! V
|
||||
return type(of: field).read(field: field, for: rawObject) as! V
|
||||
}
|
||||
self.setValue = {
|
||||
|
||||
@@ -163,11 +159,7 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
let keyPathString = field.keyPath
|
||||
self.getValue = {
|
||||
|
||||
return type(of: field).read(
|
||||
field: field,
|
||||
for: rawObject,
|
||||
bypassThreadCheck: true // May be called from NSError logs
|
||||
) as! V
|
||||
return type(of: field).read(field: field, for: rawObject) as! V
|
||||
}
|
||||
self.setValue = {
|
||||
|
||||
@@ -200,11 +192,7 @@ public struct ObjectProxy<O: CoreStoreObject> {
|
||||
let keyPathString = field.keyPath
|
||||
self.getValue = {
|
||||
|
||||
return type(of: field).read(
|
||||
field: field,
|
||||
for: rawObject,
|
||||
bypassThreadCheck: true // May be called from NSError logs
|
||||
) as! V
|
||||
return type(of: field).read(field: field, for: rawObject) as! V
|
||||
}
|
||||
self.setValue = {
|
||||
|
||||
|
||||
@@ -379,8 +379,12 @@ extension ObjectPublisher where O: CoreStoreObject {
|
||||
|
||||
return nil
|
||||
}
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = object[keyPath: member]
|
||||
return type(of: field).read(field: field, for: rawObject, bypassThreadCheck: false) as! V?
|
||||
return type(of: field).read(field: field, for: rawObject) as! V?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,8 +399,12 @@ extension ObjectPublisher where O: CoreStoreObject {
|
||||
|
||||
return nil
|
||||
}
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = object[keyPath: member]
|
||||
return type(of: field).read(field: field, for: rawObject, bypassThreadCheck: false) as! V?
|
||||
return type(of: field).read(field: field, for: rawObject) as! V?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -411,8 +419,12 @@ extension ObjectPublisher where O: CoreStoreObject {
|
||||
|
||||
return nil
|
||||
}
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = object[keyPath: member]
|
||||
return type(of: field).read(field: field, for: rawObject, bypassThreadCheck: false) as! V?
|
||||
return type(of: field).read(field: field, for: rawObject) as! V?
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -427,13 +439,12 @@ extension ObjectPublisher where O: CoreStoreObject {
|
||||
|
||||
return nil
|
||||
}
|
||||
Internals.assert(
|
||||
rawObject.isRunningInAllowedQueue() == true,
|
||||
"Attempted to access \(Internals.typeName(O.self))'s value outside it's designated queue."
|
||||
)
|
||||
let field = object[keyPath: member]
|
||||
guard let value = type(of: field).read(field: field, for: rawObject, bypassThreadCheck: false) as! V? else {
|
||||
|
||||
return nil
|
||||
}
|
||||
let nativeValue = V.cs_toNativeType(from: value)
|
||||
let snapshotValue = V.cs_valueForSnapshot(from: nativeValue)
|
||||
let snapshotValue = V.cs_valueForSnapshot(from: rawObject.objectIDs(forRelationshipNamed: field.keyPath))
|
||||
return V.cs_toPublishedType(from: snapshotValue, in: self.context)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user