1

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
}
  • 2
    What is subType? . Doesn’t seem to exist in class yet is a coding key. Also show code for DeviceType – Warren Burton May 19 '20 at 08:20
  • Does this answer your question? [How do I encode enum using NSCoder in swift?](https://stackoverflow.com/questions/26326645/how-do-i-encode-enum-using-nscoder-in-swift) – Gereon May 19 '20 at 08:20
  • 1
    @WarrenBurton I forgot to remove it because my model contains more properties but I showed only a few. I added DeviceTypes code also as You asked. – Bartosz Jastrzębski May 19 '20 at 08:26
  • Quick question why use NSCoding & NSKeyedArchiver if it's codable? It already have a serializing way. – Larme May 19 '20 at 08:56
  • @Larme I need to save my model to file and load it. I have no clue how to achieve it with Codable – Bartosz Jastrzębski May 19 '20 at 09:00
  • Why did you use Codable? For JSON? Look for `JSONEncoder()` then. – Larme May 19 '20 at 09:04
  • Because Im downloading it from Api, then I want to save it to file. I can't save it as JSON, because it contains ARWorldMap object too – Bartosz Jastrzębski May 19 '20 at 09:06
  • "Because Im downloading it from Api, then I want to save it to file. I can't save it as JSON, because it contains ARWorldMap object too " Why not save the data you downloaded directly? – Larme May 19 '20 at 10:14

1 Answers1

1

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.

Warren Burton
  • 17,451
  • 3
  • 53
  • 73