Skip to content

Commit

Permalink
Merge branch 'feature/no-codable-box-1' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
helje5 committed Feb 16, 2024
2 parents c1a963c + 28d5984 commit 85ac09a
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 113 deletions.
21 changes: 7 additions & 14 deletions Sources/ManagedModels/PersistentModel/PersistentModel+KVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,14 @@ public extension PersistentModel {

func setValue<T>(forKey key: String, to value: T) where T: Codable {
willChangeValue(forKey: key); defer { didChangeValue(forKey: key) }
setPrimitiveValue(CodableBox<T>(value), forKey: key)
setPrimitiveValue(value, forKey: key)
}

func setValue<T>(forKey key: String, to value: T)
where T: Codable & AnyOptional
{
willChangeValue(forKey: key); defer { didChangeValue(forKey: key) }
if value.isSome { setPrimitiveValue(CodableBox<T>(value), forKey: key) }
if value.isSome { setPrimitiveValue(value, forKey: key) }
else { setPrimitiveValue(nil, forKey: key) }
}

Expand All @@ -271,10 +271,7 @@ public extension PersistentModel {
fatalError("No box found for non-optional Codable value for key \(key)?")
}

if let box = value as? CodableBox<T> {
guard let value = box.value else {
fatalError("Box has no value for non-optional Codable for key \(key)?")
}
if let value = value as? T {
return value
}

Expand All @@ -288,17 +285,13 @@ public extension PersistentModel {
}
}

guard let value = value as? T else {
fatalError("Unexpected value for key \(key)? \(value)")
}
assertionFailure("Codable value is directly stored? \(value)")
return value
fatalError("Codable value type doesn't match? \(value)")
}

func getValue<T>(forKey key: String) -> T where T: Codable & AnyOptional {
willAccessValue(forKey: key); defer { didAccessValue(forKey: key) }
guard let value = primitiveValue(forKey: key) else { return .noneValue }
if let box = value as? CodableBox<T> { return box.value ?? .noneValue }
if let value = value as? T { return value }

if let data = value as? Data {
assertionFailure("Unexpected Data as primitive!")
Expand All @@ -313,7 +306,7 @@ public extension PersistentModel {
guard let value = value as? T else {
fatalError("Unexpected value for key \(key)? \(value)")
}
assertionFailure("Codable value is directly stored? \(value)")
return value
assertionFailure("Codable value type doesn't match? \(value)")
return .noneValue
}
}
86 changes: 0 additions & 86 deletions Sources/ManagedModels/SchemaCompatibility/CodableBox.swift

This file was deleted.

48 changes: 48 additions & 0 deletions Sources/ManagedModels/SchemaCompatibility/CodableTransformer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// Created by Helge Heß.
// Copyright © 2023 ZeeZide GmbH.
//

import Foundation
import CoreData

final class CodableTransformer<T: Codable>: ValueTransformer {

#if false
override class func transformedValueClass() -> AnyClass {
T.self // doesn't work
}
#endif
override class func allowsReverseTransformation() -> Bool { true }

override func transformedValue(_ value: Any?) -> Any? {
// value is the box
guard let value else { return nil }
guard let typed = value as? T else {
assertionFailure("Value to be transformed is not the right type? \(value)")
return nil
}
do {
return try JSONEncoder().encode(typed)
}
catch {
assertionFailure("Could not encode JSON value of property? \(error)")
return nil
}
}

override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let value else { return nil }
guard let data = value as? Data else {
assert(value is Data, "Reverse value is not `Data`?")
return nil
}
do {
return try JSONDecoder().decode(T.self, from: data)
}
catch {
assertionFailure("Could not decode JSON value of property? \(error)")
return nil
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ extension CoreData.NSAttributeDescription: SchemaProperty {

if let primitiveType = newValue as? CoreDataPrimitiveValue.Type {
let config = primitiveType.coreDataValue
self.attributeType = config.attributeType
self.isOptional = config.isOptional
self.attributeType = config.attributeType
self.isOptional = config.isOptional
if let newClassName = config.attributeValueClassName {
self.attributeValueClassName = newClassName
}
Expand All @@ -55,8 +55,8 @@ extension CoreData.NSAttributeDescription: SchemaProperty {
let rawType = type.RawValue.self
if let primitiveType = rawType as? CoreDataPrimitiveValue.Type {
let config = primitiveType.coreDataValue
self.attributeType = config.attributeType
self.isOptional = config.isOptional
self.attributeType = config.attributeType
self.isOptional = config.isOptional
if let newClassName = config.attributeValueClassName {
self.attributeValueClassName = newClassName
}
Expand All @@ -75,12 +75,14 @@ extension CoreData.NSAttributeDescription: SchemaProperty {
self.isOptional = newValue is any AnyOptional.Type

func setValueClassName<T: Codable>(for type: T.Type) {
self.attributeValueClassName = NSStringFromClass(CodableBox<T>.self)
#if false // doesn't work
self.attributeValueClassName = NSStringFromClass(T.self)
#endif

let name = NSStringFromClass(CodableBox<T>.Transformer.self)
let name = NSStringFromClass(CodableTransformer<T>.self)
if !ValueTransformer.valueTransformerNames().contains(.init(name)) {
// no access to valueTransformerForName?
let transformer = CodableBox<T>.Transformer()
let transformer = CodableTransformer<T>()
ValueTransformer
.setValueTransformer(transformer, forName: .init(name))
}
Expand Down
12 changes: 6 additions & 6 deletions Tests/ManagedModelTests/CodablePropertiesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ final class CodablePropertiesTests: XCTestCase {

let transformerName = try XCTUnwrap(
ValueTransformer.valueTransformerNames().first(where: {
$0.rawValue.range(of: "CodableBox11TransformerVOO17ManagedModelTests8")
$0.rawValue.range(of: "CodableTransformerVOO17ManagedModelTests8")
!= nil
})
)
let transformer = try XCTUnwrap(ValueTransformer(forName: transformerName))
_ = transformer // to clear unused-wraning

XCTAssertTrue(attribute.valueType ==
CodableBox<Fixtures.CodablePropertiesSchema.AccessSIP>.self)
XCTAssertTrue(attribute.valueType == Any.self)
// Fixtures.CodablePropertiesSchema.AccessSIP.self
XCTAssertNotNil(attribute.valueTransformerName)
XCTAssertEqual(attribute.valueTransformerName, transformerName.rawValue)
}
Expand All @@ -55,7 +55,7 @@ final class CodablePropertiesTests: XCTestCase {
// CodableBox.
let transformerName = try XCTUnwrap(
ValueTransformer.valueTransformerNames().first(where: {
$0.rawValue.range(of: "CodableBox11TransformerVOO17ManagedModelTests8")
$0.rawValue.range(of: "CodableTransformerVOO17ManagedModelTests8")
!= nil
})
)
Expand All @@ -64,8 +64,8 @@ final class CodablePropertiesTests: XCTestCase {

let attribute = try XCTUnwrap(entity.attributesByName["sip"])
XCTAssertEqual(attribute.name, "sip")
XCTAssertTrue(attribute.valueType ==
CodableBox<Fixtures.CodablePropertiesSchema.AccessSIP>.self)
XCTAssertTrue(attribute.valueType == Any.self)
// Fixtures.CodablePropertiesSchema.AccessSIP.self)
XCTAssertNotNil(attribute.valueTransformerName)
XCTAssertEqual(attribute.valueTransformerName, transformerName.rawValue)
}
Expand Down

0 comments on commit 85ac09a

Please sign in to comment.