mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-03-30 14:21:49 +02:00
Fix default encoders for top-level values
This commit is contained in:
@@ -114,7 +114,8 @@ class Person: CoreStoreObject {
|
|||||||
var customField: CustomType
|
var customField: CustomType
|
||||||
|
|
||||||
@Field.Coded(
|
@Field.Coded(
|
||||||
"job", coder: (
|
"job",
|
||||||
|
coder: (
|
||||||
encode: { $0.toData() },
|
encode: { $0.toData() },
|
||||||
decode: { $0.flatMap(Job.init(data:)) ?? .unemployed }
|
decode: { $0.flatMap(Job.init(data:)) ?? .unemployed }
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -68,89 +68,124 @@ extension DynamicSchema {
|
|||||||
for (attributeName, attribute) in attributesByName {
|
for (attributeName, attribute) in attributesByName {
|
||||||
|
|
||||||
let containerType: String
|
let containerType: String
|
||||||
if attribute.attributeType == .transformableAttributeType {
|
if attribute.isTransient || attribute.attributeType == .undefinedAttributeType {
|
||||||
|
|
||||||
if attribute.isOptional {
|
containerType = "Field.Computed"
|
||||||
|
}
|
||||||
containerType = "Transformable.Optional"
|
else if attribute.attributeType == .transformableAttributeType {
|
||||||
}
|
|
||||||
else {
|
containerType = "Field.Coded"
|
||||||
|
|
||||||
containerType = "Transformable.Required"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
if attribute.isOptional {
|
containerType = "Field.Stored"
|
||||||
|
|
||||||
containerType = "Value.Optional"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
containerType = "Value.Required"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let valueType: Any.Type
|
var valueTypeString: String
|
||||||
var defaultString = ""
|
var defaultString = ""
|
||||||
|
var coderString = ""
|
||||||
switch attribute.attributeType {
|
switch attribute.attributeType {
|
||||||
|
|
||||||
case .integer16AttributeType:
|
case .integer16AttributeType:
|
||||||
valueType = Int16.self
|
valueTypeString = String(describing: Int16.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! Int16.QueryableNativeType?).flatMap(Int16.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! Int16.QueryableNativeType?).flatMap(Int16.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
defaultString = ", initial: \(defaultValue)"
|
defaultString = " = \(defaultValue)"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .integer32AttributeType:
|
case .integer32AttributeType:
|
||||||
valueType = Int32.self
|
valueTypeString = String(describing: Int32.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! Int32.QueryableNativeType?).flatMap(Int32.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! Int32.QueryableNativeType?).flatMap(Int32.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
defaultString = ", initial: \(defaultValue)"
|
defaultString = " = \(defaultValue)"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .integer64AttributeType:
|
case .integer64AttributeType:
|
||||||
valueType = Int64.self
|
valueTypeString = String(describing: Int64.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! Int64.QueryableNativeType?).flatMap(Int64.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! Int64.QueryableNativeType?).flatMap(Int64.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
defaultString = ", initial: \(defaultValue)"
|
defaultString = " = \(defaultValue)"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .decimalAttributeType:
|
case .decimalAttributeType:
|
||||||
valueType = NSDecimalNumber.self
|
valueTypeString = String(describing: NSDecimalNumber.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! NSDecimalNumber?) {
|
if let defaultValue = (attribute.defaultValue as! NSDecimalNumber?) {
|
||||||
|
|
||||||
defaultString = ", initial: NSDecimalNumber(string: \"\(defaultValue.description(withLocale: nil))\")"
|
defaultString = " = NSDecimalNumber(string: \"\(defaultValue.description(withLocale: nil))\")"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .doubleAttributeType:
|
case .doubleAttributeType:
|
||||||
valueType = Double.self
|
valueTypeString = String(describing: Double.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! Double.QueryableNativeType?).flatMap(Double.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! Double.QueryableNativeType?).flatMap(Double.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
defaultString = ", initial: \(defaultValue)"
|
defaultString = " = \(defaultValue)"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .floatAttributeType:
|
case .floatAttributeType:
|
||||||
valueType = Float.self
|
valueTypeString = String(describing: Float.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! Float.QueryableNativeType?).flatMap(Float.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! Float.QueryableNativeType?).flatMap(Float.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
defaultString = ", initial: \(defaultValue)"
|
defaultString = " = \(defaultValue)"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .stringAttributeType:
|
case .stringAttributeType:
|
||||||
valueType = String.self
|
valueTypeString = String(describing: String.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! String.QueryableNativeType?).flatMap(String.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! String.QueryableNativeType?).flatMap(String.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
// TODO: escape strings
|
defaultString = " = \"\(defaultValue.replacingOccurrences(of: "\\", with: "\\\\"))\""
|
||||||
defaultString = ", initial: \"\(defaultValue)\""
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .booleanAttributeType:
|
case .booleanAttributeType:
|
||||||
valueType = Bool.self
|
valueTypeString = String(describing: Bool.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! Bool.QueryableNativeType?).flatMap(Bool.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! Bool.QueryableNativeType?).flatMap(Bool.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
defaultString = ", initial: \(defaultValue ? "true" : "false")"
|
defaultString = " = \(defaultValue ? "true" : "false")"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .dateAttributeType:
|
case .dateAttributeType:
|
||||||
valueType = Date.self
|
valueTypeString = String(describing: Date.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! Date.QueryableNativeType?).flatMap(Date.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! Date.QueryableNativeType?).flatMap(Date.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
defaultString = ", initial: Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))"
|
defaultString = " = Date(timeIntervalSinceReferenceDate: \(defaultValue.timeIntervalSinceReferenceDate))"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .binaryDataAttributeType:
|
case .binaryDataAttributeType:
|
||||||
valueType = Data.self
|
valueTypeString = String(describing: Data.self)
|
||||||
if let defaultValue = (attribute.defaultValue as! Data.QueryableNativeType?).flatMap(Data.cs_fromQueryableNativeType) {
|
if let defaultValue = (attribute.defaultValue as! Data.QueryableNativeType?).flatMap(Data.cs_fromQueryableNativeType) {
|
||||||
|
|
||||||
let bytes = defaultValue.withUnsafeBytes { (pointer) in
|
let bytes = defaultValue.withUnsafeBytes { (pointer) in
|
||||||
@@ -158,49 +193,106 @@ extension DynamicSchema {
|
|||||||
.bindMemory(to: UInt64.self)
|
.bindMemory(to: UInt64.self)
|
||||||
.map({ "\("0x\(String($0, radix: 16, uppercase: false))")" })
|
.map({ "\("0x\(String($0, radix: 16, uppercase: false))")" })
|
||||||
}
|
}
|
||||||
defaultString = ", initial: Data(bytes: [\(bytes.joined(separator: ", "))])"
|
defaultString = " = Data(bytes: [\(bytes.joined(separator: ", "))])"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
case .transformableAttributeType:
|
case .transformableAttributeType:
|
||||||
|
if let valueTransformerName = attribute.valueTransformerName {
|
||||||
|
|
||||||
|
coderString = ", coder: /* Required compatible FieldCoderType implementation for ValueTransformer named \"\(valueTransformerName)\" */"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
coderString = ", coder: FieldCoders.NSCoding.self"
|
||||||
|
}
|
||||||
if let attributeValueClassName = attribute.attributeValueClassName {
|
if let attributeValueClassName = attribute.attributeValueClassName {
|
||||||
|
|
||||||
valueType = NSClassFromString(attributeValueClassName)!
|
valueTypeString = String(describing: NSClassFromString(attributeValueClassName)!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
valueTypeString = "/* <required> */"
|
||||||
|
}
|
||||||
|
if let defaultValue = attribute.defaultValue {
|
||||||
|
|
||||||
|
switch defaultValue {
|
||||||
|
|
||||||
|
case let defaultValueBox as Internals.AnyFieldCoder.TransformableDefaultValueCodingBox:
|
||||||
|
if let defaultValue = defaultValueBox.value {
|
||||||
|
|
||||||
|
defaultString = " = /* \"\(defaultValue)\" */"
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
defaultString = " = nil"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
defaultString = " = /* <required> */"
|
||||||
|
}
|
||||||
|
|
||||||
|
case let defaultValue:
|
||||||
|
defaultString = " = /* \"\(defaultValue)\" */"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if attribute.isOptional {
|
||||||
|
|
||||||
|
defaultString = " = nil"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
valueType = (NSCoding & NSCopying).self
|
defaultString = " = /* <required> */"
|
||||||
}
|
}
|
||||||
if let defaultValue = attribute.defaultValue {
|
if attribute.isOptional {
|
||||||
|
|
||||||
defaultString = ", initial: /* \"\(defaultValue)\" */"
|
valueTypeString += "?"
|
||||||
}
|
}
|
||||||
else if !attribute.isOptional {
|
|
||||||
|
case .undefinedAttributeType where attribute.isTransient:
|
||||||
defaultString = ", initial: /* required */"
|
coderString = ", customGetter: \\* <required> *\\"
|
||||||
|
if let attributeValueClassName = attribute.attributeValueClassName {
|
||||||
|
|
||||||
|
valueTypeString = String(describing: NSClassFromString(attributeValueClassName)!)
|
||||||
}
|
}
|
||||||
case .undefinedAttributeType:
|
else {
|
||||||
#warning("TODO: Field.Computed")
|
|
||||||
continue
|
valueTypeString = " = /* <required> */"
|
||||||
|
}
|
||||||
|
if attribute.isOptional {
|
||||||
|
|
||||||
|
valueTypeString += "?"
|
||||||
|
defaultString = " = nil"
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatalError("Unsupported attribute type: \(attribute.attributeType.rawValue)")
|
fatalError("Unsupported attribute type: \(attribute.attributeType.rawValue)")
|
||||||
}
|
}
|
||||||
let transientString = attribute.isTransient ? ", isTransient: true" : ""
|
|
||||||
// TODO: escape strings
|
|
||||||
let versionHashModifierString = attribute.versionHashModifier
|
let versionHashModifierString = attribute.versionHashModifier
|
||||||
.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
.map({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||||
// TODO: escape strings
|
|
||||||
let renamingIdentifierString = attribute.renamingIdentifier
|
let renamingIdentifierString = attribute.renamingIdentifier
|
||||||
.flatMap({ ($0 == attributeName ? "" : ", renamingIdentifier: \"\($0)\"") as String }) ?? ""
|
.map({ ($0 == attributeName ? "" : ", previousVersionKeyPath: \"\($0)\"") }) ?? ""
|
||||||
output.append(" let \(attributeName) = \(containerType)<\(String(describing: valueType))>(\"\(attributeName)\"\(defaultString)\(transientString)\(versionHashModifierString)\(renamingIdentifierString))\n")
|
if attributeName.hasPrefix("_") {
|
||||||
|
|
||||||
|
output.append(" #warning(\"Field variable names cannot start with underscores)")
|
||||||
|
}
|
||||||
|
output.append(" @\(containerType)(\"\(attributeName)\"\(versionHashModifierString)\(renamingIdentifierString)\(coderString))\n")
|
||||||
|
output.append(" var \(attributeName): \(valueTypeString)\(defaultString)\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let relationshipsByName = entity.relationshipsByName
|
let relationshipsByName = entity.relationshipsByName
|
||||||
if !relationshipsByName.isEmpty {
|
if !relationshipsByName.isEmpty {
|
||||||
|
|
||||||
output.append(" \n")
|
output.append(" \n")
|
||||||
for (relationshipName, relationship) in relationshipsByName {
|
for (relationshipName, relationship) in relationshipsByName {
|
||||||
|
|
||||||
let containerType: String
|
let containerType: String
|
||||||
|
let destinationEntityName = relationship.destinationEntity!.name!
|
||||||
var minCountString = ""
|
var minCountString = ""
|
||||||
var maxCountString = ""
|
var maxCountString = ""
|
||||||
if relationship.isToMany {
|
if relationship.isToMany {
|
||||||
@@ -209,11 +301,11 @@ extension DynamicSchema {
|
|||||||
let maxCount = relationship.maxCount
|
let maxCount = relationship.maxCount
|
||||||
if relationship.isOrdered {
|
if relationship.isOrdered {
|
||||||
|
|
||||||
containerType = "Relationship.ToManyOrdered"
|
containerType = "[\(destinationEntityName)]"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
containerType = "Relationship.ToManyUnordered"
|
containerType = "Set<\(destinationEntityName)>"
|
||||||
}
|
}
|
||||||
if minCount > 0 {
|
if minCount > 0 {
|
||||||
|
|
||||||
@@ -225,16 +317,16 @@ extension DynamicSchema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
containerType = "Relationship.ToOne"
|
containerType = "\(destinationEntityName)?"
|
||||||
}
|
}
|
||||||
var inverseString = ""
|
var inverseString = ""
|
||||||
let relationshipQualifier = "\(entityName).\(relationshipName)"
|
let relationshipQualifier = "\(entityName).\(relationshipName)"
|
||||||
if !addedInverse.contains(relationshipQualifier),
|
if !addedInverse.contains(relationshipQualifier),
|
||||||
let inverseRelationship = relationship.inverseRelationship {
|
let inverseRelationship = relationship.inverseRelationship {
|
||||||
|
|
||||||
inverseString = ", inverse: { $0.\(inverseRelationship.name) }"
|
inverseString = ", inverse: \\.$\(inverseRelationship.name)"
|
||||||
addedInverse.insert("\(relationship.destinationEntity!.name!).\(inverseRelationship.name)")
|
addedInverse.insert("\(destinationEntityName).\(inverseRelationship.name)")
|
||||||
}
|
}
|
||||||
var deleteRuleString = ""
|
var deleteRuleString = ""
|
||||||
if relationship.deleteRule != .nullifyDeleteRule {
|
if relationship.deleteRule != .nullifyDeleteRule {
|
||||||
@@ -255,10 +347,15 @@ extension DynamicSchema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let versionHashModifierString = relationship.versionHashModifier
|
let versionHashModifierString = relationship.versionHashModifier
|
||||||
.flatMap({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
.map({ ", versionHashModifier: \"\($0)\"" }) ?? ""
|
||||||
let renamingIdentifierString = relationship.renamingIdentifier
|
let renamingIdentifierString = relationship.renamingIdentifier
|
||||||
.flatMap({ ($0 == relationshipName ? "" : ", renamingIdentifier: \"\($0)\"") as String }) ?? ""
|
.map({ ($0 == relationshipName ? "" : ", previousVersionKeyPath: \"\($0)\"") }) ?? ""
|
||||||
output.append(" let \(relationshipName) = \(containerType)<\(relationship.destinationEntity!.name!)>(\"\(relationshipName)\"\(inverseString)\(deleteRuleString)\(minCountString)\(maxCountString)\(versionHashModifierString)\(renamingIdentifierString))\n")
|
if relationshipName.hasPrefix("_") {
|
||||||
|
|
||||||
|
output.append(" #error(\"Field variable names cannot start with underscores)\n")
|
||||||
|
}
|
||||||
|
output.append(" @Field.Relationship(\"\(relationshipName)\"\(minCountString)\(maxCountString)\(inverseString)\(deleteRuleString)\(versionHashModifierString)\(renamingIdentifierString))\n")
|
||||||
|
output.append(" var \(relationshipName): \(containerType)\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,40 @@ extension FieldContainer {
|
|||||||
// @dynamicMemberLookup
|
// @dynamicMemberLookup
|
||||||
public struct Relationship<V: FieldRelationshipType>: RelationshipKeyPathStringConvertible, FieldRelationshipProtocol {
|
public struct Relationship<V: FieldRelationshipType>: RelationshipKeyPathStringConvertible, FieldRelationshipProtocol {
|
||||||
|
|
||||||
public typealias DeleteRule = RelationshipContainer<O>.DeleteRule
|
/**
|
||||||
|
Overload for compiler error message only
|
||||||
|
*/
|
||||||
|
@available(*, unavailable, message: "Field.Relationship properties are not allowed to have initial values, including `nil`.")
|
||||||
|
public init(
|
||||||
|
wrappedValue initial: @autoclosure @escaping () -> V,
|
||||||
|
_ keyPath: KeyPathString,
|
||||||
|
minCount: Int = 0,
|
||||||
|
maxCount: Int = 0,
|
||||||
|
deleteRule: DeleteRule = .nullify,
|
||||||
|
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||||
|
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil
|
||||||
|
) {
|
||||||
|
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Overload for compiler error message only
|
||||||
|
*/
|
||||||
|
@available(*, unavailable, message: "Field.Relationship properties are not allowed to have initial values, including `nil`.")
|
||||||
|
public init<D>(
|
||||||
|
wrappedValue initial: @autoclosure @escaping () -> V,
|
||||||
|
_ keyPath: KeyPathString,
|
||||||
|
minCount: Int = 0,
|
||||||
|
maxCount: Int = 0,
|
||||||
|
inverse: KeyPath<V.DestinationObjectType, FieldContainer<V.DestinationObjectType>.Relationship<D>>,
|
||||||
|
deleteRule: DeleteRule = .nullify,
|
||||||
|
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||||
|
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil
|
||||||
|
) {
|
||||||
|
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: @propertyWrapper
|
// MARK: @propertyWrapper
|
||||||
@@ -188,6 +221,45 @@ extension FieldContainer {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - DeleteRule
|
||||||
|
|
||||||
|
/**
|
||||||
|
These constants define what happens to relationships when an object is deleted.
|
||||||
|
*/
|
||||||
|
public enum DeleteRule {
|
||||||
|
|
||||||
|
// MARK: Public
|
||||||
|
|
||||||
|
/**
|
||||||
|
If the object is deleted, back pointers from the objects to which it is related are nullified.
|
||||||
|
*/
|
||||||
|
case nullify
|
||||||
|
|
||||||
|
/**
|
||||||
|
If the object is deleted, the destination object or objects of this relationship are also deleted.
|
||||||
|
*/
|
||||||
|
case cascade
|
||||||
|
|
||||||
|
/**
|
||||||
|
If the destination of this relationship is not nil, the delete creates a validation error.
|
||||||
|
*/
|
||||||
|
case deny
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Internal
|
||||||
|
|
||||||
|
internal var nativeValue: NSDeleteRule {
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
|
||||||
|
case .nullify: return .nullifyDeleteRule
|
||||||
|
case .cascade: return .cascadeDeleteRule
|
||||||
|
case .deny: return .denyDeleteRule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +343,7 @@ extension FieldContainer.Relationship where V: FieldRelationshipToManyOrderedTyp
|
|||||||
_ keyPath: KeyPathString,
|
_ keyPath: KeyPathString,
|
||||||
minCount: Int = 0,
|
minCount: Int = 0,
|
||||||
maxCount: Int = 0,
|
maxCount: Int = 0,
|
||||||
inverse: @escaping (V.DestinationObjectType) -> FieldContainer<V.DestinationObjectType>.Relationship<D>,
|
inverse: KeyPath<V.DestinationObjectType, FieldContainer<V.DestinationObjectType>.Relationship<D>>,
|
||||||
deleteRule: DeleteRule = .nullify,
|
deleteRule: DeleteRule = .nullify,
|
||||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||||
@@ -283,7 +355,7 @@ extension FieldContainer.Relationship where V: FieldRelationshipToManyOrderedTyp
|
|||||||
isToMany: true,
|
isToMany: true,
|
||||||
isOrdered: true,
|
isOrdered: true,
|
||||||
deleteRule: deleteRule,
|
deleteRule: deleteRule,
|
||||||
inverseKeyPath: { inverse(V.DestinationObjectType.meta).keyPath },
|
inverseKeyPath: { V.DestinationObjectType.meta[keyPath: inverse].keyPath },
|
||||||
versionHashModifier: versionHashModifier,
|
versionHashModifier: versionHashModifier,
|
||||||
renamingIdentifier: previousVersionKeyPath,
|
renamingIdentifier: previousVersionKeyPath,
|
||||||
affectedByKeyPaths: affectedByKeyPaths,
|
affectedByKeyPaths: affectedByKeyPaths,
|
||||||
@@ -323,7 +395,7 @@ extension FieldContainer.Relationship where V: FieldRelationshipToManyUnorderedT
|
|||||||
_ keyPath: KeyPathString,
|
_ keyPath: KeyPathString,
|
||||||
minCount: Int = 0,
|
minCount: Int = 0,
|
||||||
maxCount: Int = 0,
|
maxCount: Int = 0,
|
||||||
inverse: @escaping (V.DestinationObjectType) -> FieldContainer<V.DestinationObjectType>.Relationship<D>,
|
inverse: KeyPath<V.DestinationObjectType, FieldContainer<V.DestinationObjectType>.Relationship<D>>,
|
||||||
deleteRule: DeleteRule = .nullify,
|
deleteRule: DeleteRule = .nullify,
|
||||||
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
versionHashModifier: @autoclosure @escaping () -> String? = nil,
|
||||||
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
previousVersionKeyPath: @autoclosure @escaping () -> String? = nil,
|
||||||
@@ -335,7 +407,7 @@ extension FieldContainer.Relationship where V: FieldRelationshipToManyUnorderedT
|
|||||||
isToMany: true,
|
isToMany: true,
|
||||||
isOrdered: false,
|
isOrdered: false,
|
||||||
deleteRule: deleteRule,
|
deleteRule: deleteRule,
|
||||||
inverseKeyPath: { inverse(V.DestinationObjectType.meta).keyPath },
|
inverseKeyPath: { V.DestinationObjectType.meta[keyPath: inverse].keyPath },
|
||||||
versionHashModifier: versionHashModifier,
|
versionHashModifier: versionHashModifier,
|
||||||
renamingIdentifier: previousVersionKeyPath,
|
renamingIdentifier: previousVersionKeyPath,
|
||||||
affectedByKeyPaths: affectedByKeyPaths,
|
affectedByKeyPaths: affectedByKeyPaths,
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ extension FieldCoders {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return try? JSONEncoder().encode(fieldValue)
|
return try! JSONEncoder().encode([fieldValue])
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func decodeFromStoredData(_ data: Data?) -> FieldStoredValue? {
|
public static func decodeFromStoredData(_ data: Data?) -> FieldStoredValue? {
|
||||||
@@ -53,7 +53,7 @@ extension FieldCoders {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return try? JSONDecoder().decode(FieldStoredValue.self, from: data)
|
return try! JSONDecoder().decode([FieldStoredValue].self, from: data).first
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ extension FieldCoders {
|
|||||||
|
|
||||||
// MARK: - NSCoding
|
// MARK: - NSCoding
|
||||||
|
|
||||||
public struct NSCoding<V: NSObject & Foundation.NSCoding>: FieldCoderType {
|
public struct NSCoding<V: Foundation.NSObject & Foundation.NSCoding>: FieldCoderType {
|
||||||
|
|
||||||
// MARK: FieldCoderType
|
// MARK: FieldCoderType
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ extension FieldCoders {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return try? PropertyListEncoder().encode(fieldValue)
|
return try! PropertyListEncoder().encode([fieldValue])
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func decodeFromStoredData(_ data: Data?) -> FieldStoredValue? {
|
public static func decodeFromStoredData(_ data: Data?) -> FieldStoredValue? {
|
||||||
@@ -53,7 +53,7 @@ extension FieldCoders {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return try? PropertyListDecoder().decode(FieldStoredValue.self, from: data)
|
return try! PropertyListDecoder().decode([FieldStoredValue].self, from: data).first
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,10 @@ extension DynamicObject where Self: CoreStoreObject {
|
|||||||
public enum RelationshipContainer<O: CoreStoreObject> {
|
public enum RelationshipContainer<O: CoreStoreObject> {
|
||||||
|
|
||||||
// MARK: - DeleteRule
|
// MARK: - DeleteRule
|
||||||
|
|
||||||
|
/**
|
||||||
|
These constants define what happens to relationships when an object is deleted.
|
||||||
|
*/
|
||||||
public enum DeleteRule {
|
public enum DeleteRule {
|
||||||
|
|
||||||
// MARK: Public
|
// MARK: Public
|
||||||
|
|||||||
Reference in New Issue
Block a user