Reputation: 553
In my iOS app, I have the following struct
s:
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.
Upvotes: 0
Views: 121
Reputation: 30746
You need to delete those structs and visit the model editor first create entities for the Exercise and ExerciseGroup and create the relation and inverse relation between them. Also delete the ExerciseGroupStorage
. Then use Editor->Create NSManagedObject subclass. Then you need to select each entity and in the right panel choose Codegen: Category/Extension. You also need to delete the generated files except for the ones that have the suffix +CoreDataClass.swift
Since these are classes you can now create instances properly. Fyi structs are just values not instances. It might take a few builds, cleans or restarting Xcode to get the files to be detected.
Upvotes: 0
Reputation: 70976
The immediate problem is that you can’t use Transformable
with Codable
. Transformable works with NSCoding
, which does something very similar to Codable
but is not compatible with it. Changing to NSCoding
isn’t as simple as it might seem though, because you can really only use it on classes that inherit from NSObject
. It will not work on a Swift struct.
You could, if you want, use a Data
attribute and write your own code to convert the structs to/from Data
. 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.
Upvotes: 0