In my iOS app, I have the following structs:
struct ExerciseGroup: Decodable, Identifiable {
var id: String = "loading"
var name: String = "loading
var exercises: [Exercise] = []
}
struct Exercise: Decodable, Identifiable {
var id: String = "loading"
var exerciseName: String = "loading"
}
When my code starts up, I create 2 instances of Exercise and then create an instance of ExerciseGroup whose exercises property is populated with the 2 Exercise instances.
var exercises: [Exercise] = []
exercises.append(Exercise(id: "1", exerciseName: "exercise1")
exercises.append(Exercise(id: "2", exerciseName: "exercise2")
exerciseGroup.append(ExerciseGroup(
id: "a", name: "myGroup", exercises: exercises)
))
Using managedObjectContext.save(), I want to persist this exerciseGroup to Core Data storage. I have a model called ExerciseStorageModel.xcdatamodel which contains the entity ExerciseGroupStorage; that has the attributes:
id: String
name: String
exercises: Transformable // I think this is what is needed
To populate the entity for saving, I use:
_ = exerciseGroups.map { eg in
do {
exerciseGroupStorage.id = eg.id
exerciseGroupStorage.name = eg.name
exerciseGroupStorage.exercises = eg.exercises as NSObject // I'm not sure about this...
try managedObjectContext.save()
} catch {/* print error */}
}
When I run the app and attempt to save(), I get the error message:
CoreData: error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
What do I need to do to store ExerciseGroupStorage with the exercises array as the content of the exercises attribute? Thank you.
The immediate problem is that you can’t use
TransformablewithCodable. Transformable works withNSCoding, which does something very similar toCodablebut is not compatible with it. Changing toNSCodingisn’t as simple as it might seem though, because you can really only use it on classes that inherit fromNSObject. It will not work on a Swift struct.You could, if you want, use a
Dataattribute and write your own code to convert the structs to/fromData. But that leads to the second problem, which is that this is not a good use of Core Data. You’re wrapping all of your data into a binary field, which can’t be used for filtering or sorting. You’re forcing data into Core Data while losing pretty much every advantage of using Core Data. You should probably either use managed objects for your data so that Core Data will be useful, or else not use Core Data and find some other way to save your data.