I am getting model from Api and it looks like this:
class Device : NSObject, Codable, NSCoding{
var deviceId : Int?
var driver : String?
var address : String?
var type : DeviceTypes? // Enum type
func encode(with coder: NSCoder) {
coder.encode(self.deviceId, forKey: "deviceId")
coder.encode(self.driver, forKey: "driver")
coder.encode(self.address, forKey: "address")
coder.encode(self.type, forKey: CodingKeys.type.rawValue)
}
required init?(coder: NSCoder) {
super.init()
self.deviceId = coder.decodeInteger(forKey: "deviceId")
self.driver = coder.decodeObject(forKey: "driver") as? String
self.address = coder.decodeObject(forKey: "address") as? String
self.type = coder.decodeObject(forKey: CodingKeys.type.rawValue) as? DeviceTypes
}
private enum CodingKeys : String, CodingKey{
case deviceId, address, type, deviceType
}
}
Then I am adding some elements to array and it works but when I am trying to archive it with NSKeyedArchiver it throws an Exception :
[__SwiftValue encodeWithCoder:]: unrecognized selector sent to instance
DeviceTypes
enum DeviceTypes : Int, Codable{
case SYSTEM
case CE
case CZ
case ST
case KA
case CR
case EX
case DR
case KL
case WE
case WY
case WL
case TR
case LI
case BR = 30
case DC = 32
}
Your problem is NSCoding
is only available for class types. Any attempt to conform DeviceTypes
to NSCoding
will result in an error
enum DeviceTypes : Int, Codable, NSCoding {
Non-class type 'DeviceTypes' cannot conform to class protocol 'NSCoding'
One solution is to convert back and forth from the enum
type in your NSCoding
methods.
Note that NSCoding
is soft deprecated for NSSecureCoding
so you should use that conformance to avoid future support issues.
class Device : NSObject, NSSecureCoding {
static var supportsSecureCoding: Bool = true
var deviceId : Int?
var driver : String?
var address : String?
var type : DeviceTypes? // Enum type
func encode(with coder: NSCoder) {
coder.encode(self.deviceId, forKey: "deviceId")
coder.encode(self.driver, forKey: "driver")
coder.encode(self.address, forKey: "address")
coder.encode(self.type?.rawValue, forKey: "type")
}
required init?(coder: NSCoder) {
super.init()
self.deviceId = coder.decodeInteger(forKey: "deviceId")
self.driver = coder.decodeObject(forKey: "driver") as? String
self.address = coder.decodeObject(forKey: "address") as? String
let rawtype = coder.decodeInteger(forKey: "type")
self.type = DeviceTypes(rawValue: rawtype)
}
}
You haven't supplied all the code in your Device
class as your post fragment doesn't compile with Codable
conformance so I can't guess at what your system really requires in terms of JSON support.