How do you save a custom class as an attribute of a CoreData entity in Swift 3?

Viewed 7391

I have a CoreData Entity SavedWorkout. It has the following attributes: enter image description here

completionCounter is an array of Bool, and workout is a custom class called Workout.

I am saving my data like so:

let saveCompletionCounter = currentCompletionCounter
let saveDate = Date() as NSDate
let saveRoutineIndex = Int16(currentWorkoutRoutine)
let saveWorkout = NSKeyedArchiver.archivedData(withRootObject: workout)

item.setValue(saveDate, forKey: "date")
item.setValue(saveWorkout, forKey: "workout")
item.setValue(saveRoutineIndex, forKey: "routineIndex")
item.setValue(saveCompletionCounter, forKey: "completionCounter")

do {
  try moc.save()
  print("save successful")
} catch {
  print("saving error")
}

where moc is an instance of NSManagedObjectContext, and item is an instance of NSManagedObject:

moc = appDelegate.managedObjectContext
entity = NSEntityDescription.entity(forEntityName: "SavedWorkout", in: moc)!
item = NSManagedObject(entity: entity, insertInto: moc)

In accordance with this and this and this , I have made my Workout class conform to NSObject and NSCoding, so it now looks like this:

class Workout: NSObject, NSCoding {

  let name: String
  let imageName: String
  let routine: [WorkoutRoutine]
  let shortDescription: String

  required init?(coder aDecoder: NSCoder) {
    name = aDecoder.decodeObject(forKey: "name") as! String
    imageName = aDecoder.decodeObject(forKey: "imageName") as! String
    routine = aDecoder.decodeObject(forKey: "routine") as! [WorkoutRoutine]
    shortDescription = aDecoder.decodeObject(forKey: "shortDescription") as! String
  }

  func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "name")
    aCoder.encode(imageName, forKey: "imageName")
    aCoder.encode(routine, forKey: "routine")
    aCoder.encode(shortDescription, forKey: "shortDescription")
  }

  init(name: String, imageName: String, routine: [WorkoutRoutine], shortDescription: String) {
    self.name = name
    self.imageName = imageName
    self.routine = routine
    self.shortDescription = shortDescription
  }
}

However I always get an error on the line routine: aDecoder.decodeObject....

The error says:

NSForwarding: warning: object 0x60800002cbe0 of class 'App.WorkoutRoutine' does not implement methodSignatureForSelector: -- trouble ahead

Unrecognized selector -[FitLift.WorkoutRoutine replacementObjectForKeyedArchiver:]

Why does this give me an error and not the other Transformable attribute? How do I save a custom class as a property of a CoreData entity?

1 Answers
Related