So here is stripped down code for my base object 'Aircraft', and the object that inherits from it - C172RS. (this object adds a few properties and includes some different behaviours)
At the bottom is 'AircraftStore' it contains an array of aircraft to be saved. When 'aircraftArray' contains only base objects (Aircraft) the save function works fine. If an inherited object is in the list, NSKeyedArchier.archivedData fails.
import Foundation
class Aircraft: NSObject, NSSecureCoding {
//MARK: - Properties
static var supportsSecureCoding: Bool = true
let registration: String
var emptyWeight: Double = 1200
var fuelVolume: Double = 38
var load: Load = Load()
//MARK: - Initialization
init(withRegistration registration: String = "AC_REG", emptyWeight lbs: Double = 1200) {
self.registration = registration
self.emptyWeight = lbs
super.init()
}
required init?(coder: NSCoder) {
registration = coder.decodeObject(forKey: "registration") as! String
emptyWeight = coder.decodeDouble(forKey: "emptyWeight")
fuelVolume = coder.decodeDouble(forKey: "fuelVolume")
load = coder.decodeObject(of: Load.self, forKey: "load") ?? Load()
}
func encode(with coder: NSCoder) {
coder.encode(registration, forKey: "registration")
coder.encode(emptyWeight, forKey: "emptyWeight")
coder.encode(fuelVolume, forKey: "fuelVolume")
coder.encode(load, forKey: "load")
}
}
class C172RS: Aircraft {
//MARK: - Properties
var model: Model = .R
var prop: Prop = .MTV
var modKit: Bool = false
var stc: Bool = false
//MARK: - Initialization
override init(withRegistration registration: String = "AC_REG", emptyWeight lbs: Double = 1400) {
super.init(withRegistration: registration, emptyWeight: lbs)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
model = Model(rawValue: coder.decodeInteger(forKey: "model"))!
prop = Prop(rawValue: coder.decodeInteger(forKey: "prop"))!
stc = coder.decodeBool(forKey: "stc")
modKit = coder.decodeBool(forKey: "modkit")
}
override func encode(with coder: NSCoder) {
super.encode(with: coder)
coder.encode(model.rawValue, forKey: "model")
coder.encode(prop.rawValue, forKey: "prop")
coder.encode(stc, forKey: "stc")
coder.encode(modKit, forKey: "modkit")
}
}
class AircraftStore {
//MARK: - Properties
private var aircraftArray = [Aircraft]()
private let url = ACFunction.archiveURL(fileName: "AircraftStore.data")
var count: Int { return aircraftArray.count }
//MARK: - Initialization
init() {
do {
let data = try Data(contentsOf: url)
if let saveArray = try NSKeyedUnarchiver.unarchivedArrayOfObjects(ofClasses: [Aircraft.self, NSString.self], from: data) {
aircraftArray = saveArray as! [Aircraft]
}
print("AircraftStore.init unarchive success \(count) aircraft")
} catch {
print("AircraftStore.init unarchive failed")
}
}
func save() {
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: aircraftArray, requiringSecureCoding: true)
try data.write(to: url)
print("AircraftStore.save success")
} catch {
print("AircraftStore.save failed")
}
}