55
66import CoreData
77
8+ // Note: This needs to match up the `valueType` in NSAttributeDescription+Data.
9+
810// MARK: - Primitives
911public extension PersistentModel {
1012
1113 @inlinable
1214 func setValue< T> ( forKey key: String , to value: T )
13- where T: Encodable & CoreDataPrimitiveValue
15+ where T: Codable & CoreDataPrimitiveValue
1416 {
1517 willChangeValue ( forKey: key) ; defer { didChangeValue ( forKey: key) }
1618 setPrimitiveValue ( value, forKey: key)
1719 }
1820
1921 @inlinable
2022 func getValue< T> ( forKey key: String ) -> T
21- where T: Decodable & CoreDataPrimitiveValue
23+ where T: Codable & CoreDataPrimitiveValue
24+ {
25+ willAccessValue ( forKey: key) ; defer { didAccessValue ( forKey: key) }
26+ return primitiveValue ( forKey: key) as! T
27+ }
28+
29+ @inlinable
30+ func setValue< T> ( forKey key: String , to value: T )
31+ where T: Codable & CoreDataPrimitiveValue & AnyOptional
32+ {
33+ willChangeValue ( forKey: key) ; defer { didChangeValue ( forKey: key) }
34+ setPrimitiveValue ( value, forKey: key)
35+ }
36+ @inlinable
37+ func getValue< T> ( forKey key: String ) -> T
38+ where T: Codable & CoreDataPrimitiveValue & AnyOptional
2239 {
2340 willAccessValue ( forKey: key) ; defer { didAccessValue ( forKey: key) }
2441 return primitiveValue ( forKey: key) as! T
@@ -163,14 +180,14 @@ public extension PersistentModel {
163180
164181 @inlinable
165182 func setValue< T> ( forKey key: String , to value: T )
166- where T: RawRepresentable , T. RawValue: Encodable & CoreDataPrimitiveValue
183+ where T: RawRepresentable , T. RawValue: Codable & CoreDataPrimitiveValue
167184 {
168185 setValue ( forKey: key, to: value. rawValue)
169186 }
170187
171188 @inlinable
172189 func getValue< T> ( forKey key: String ) -> T
173- where T: RawRepresentable , T. RawValue: Decodable & CoreDataPrimitiveValue
190+ where T: RawRepresentable , T. RawValue: Codable & CoreDataPrimitiveValue
174191 {
175192 let rawValue : T . RawValue = getValue ( forKey: key)
176193 guard let wrapped = T . init ( rawValue: rawValue) else {
@@ -185,25 +202,68 @@ public extension PersistentModel {
185202 // SwiftData is doing a Codable a little different.
186203 // TBD: we could also use transformers for this, probably faster?!
187204
188- @inlinable
189- func setValue< T> ( forKey key: String , to value: T ) where T: Encodable {
190- do {
191- let data = try JSONEncoder ( ) . encode ( value)
192- setValue ( forKey: key, to: data)
205+ func setValue< T> ( forKey key: String , to value: T ) where T: Codable {
206+ willChangeValue ( forKey: key) ; defer { didChangeValue ( forKey: key) }
207+ setPrimitiveValue ( CodableBox < T > ( value) , forKey: key)
208+ }
209+
210+ func setValue< T> ( forKey key: String , to value: T )
211+ where T: Codable & AnyOptional
212+ {
213+ willChangeValue ( forKey: key) ; defer { didChangeValue ( forKey: key) }
214+ if value. isSome { setPrimitiveValue ( CodableBox < T > ( value) , forKey: key) }
215+ else { setPrimitiveValue ( nil , forKey: key) }
216+ }
217+
218+ func getValue< T> ( forKey key: String ) -> T where T: Codable {
219+ willAccessValue ( forKey: key) ; defer { didAccessValue ( forKey: key) }
220+ guard let value = primitiveValue ( forKey: key) else {
221+ fatalError ( " No box found for non-optional Codable value for key \( key) ? " )
222+ }
223+
224+ if let box = value as? CodableBox < T > {
225+ guard let value = box. value else {
226+ fatalError ( " Box has no value for non-optional Codable for key \( key) ? " )
227+ }
228+ return value
193229 }
194- catch {
195- fatalError ( " Could not encode JSON value for key \( key) ? \( error) " )
230+
231+ if let data = value as? Data {
232+ assertionFailure ( " Unexpected Data as primitive! " )
233+ do {
234+ return try JSONDecoder ( ) . decode ( T . self, from: data)
235+ }
236+ catch {
237+ fatalError ( " Could not decode JSON value for key \( key) ? \( error) " )
238+ }
196239 }
240+
241+ guard let value = value as? T else {
242+ fatalError ( " Unexpected value for key \( key) ? \( value) " )
243+ }
244+ assertionFailure ( " Codable value is directly stored? \( value) " )
245+ return value
197246 }
198247
199- @inlinable
200- func getValue< T> ( forKey key: String ) -> T where T: Decodable {
201- let data : Data ? = getValue ( forKey: key)
202- do {
203- return try JSONDecoder ( ) . decode ( T . self, from: data ?? Data ( ) )
248+ func getValue< T> ( forKey key: String ) -> T where T: Codable & AnyOptional {
249+ willAccessValue ( forKey: key) ; defer { didAccessValue ( forKey: key) }
250+ guard let value = primitiveValue ( forKey: key) else { return . noneValue }
251+ if let box = value as? CodableBox < T > { return box. value ?? . noneValue }
252+
253+ if let data = value as? Data {
254+ assertionFailure ( " Unexpected Data as primitive! " )
255+ do {
256+ return try JSONDecoder ( ) . decode ( T . self, from: data)
257+ }
258+ catch {
259+ fatalError ( " Could not decode JSON value for key \( key) ? \( error) " )
260+ }
204261 }
205- catch {
206- fatalError ( " Could not decode JSON value for key \( key) ? \( error) " )
262+
263+ guard let value = value as? T else {
264+ fatalError ( " Unexpected value for key \( key) ? \( value) " )
207265 }
266+ assertionFailure ( " Codable value is directly stored? \( value) " )
267+ return value
208268 }
209269}
0 commit comments