2

I have enum like this:

   enum Direction : String {
      case EAST  = "east"
      case SOUTH = "south"
      case WEST  = "west"
      case NORTH = "north"
    }

And I have a variable called result which is a Hashmap using these enum direction as the key.

var result = [Direction:[String]]()

I tried to encode this object and send to the other side through the multipeer framework. However, it fails at the encoder.

aCoder.encode(self.result, forKey: "result")

Error says that: "encode(with aCoder: NSCoder) *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x17045f230'

How can I encode this Hashmap?

Thanks.

user6539552
  • 1,331
  • 2
  • 19
  • 39
  • 2
    Note that it's Swift convention to use `lowerCamelCase` for enum cases (this isn't Java!). I also assume you're referring to `Dictionary` when you say Hashmap. Also `var result = [Direction[String]]` is not valid Swift, did you mean `var result = [Direction : [String]]()` or `var result : [Direction : [String]]`? – Hamish Dec 28 '16 at 18:38
  • Here's a duplicate article. http://stackoverflow.com/questions/24562357/how-can-i-use-a-swift-enum-as-a-dictionary-key-conforming-to-equatable – mrabins Dec 28 '16 at 18:45
  • yes, i mean var result = [Direction : [String]]() – user6539552 Dec 28 '16 at 19:28
  • It is not a duplication of the question. What i am asking is how to serialise (encode) the object. – user6539552 Dec 28 '16 at 19:29
  • 2
    Related: [How do I encode enum using NSCoder in swift?](http://stackoverflow.com/questions/26326645/how-do-i-encode-enum-using-nscoder-in-swift). Use the enum's `rawValue`. – JAL Dec 28 '16 at 19:37

1 Answers1

4

As noted in JAL's comment NSCoding feature is based on Objective-C runtime, so you need to convert your Dictionary to something which is safely convertible to NSDictionary.

For example:

func encode(with aCoder: NSCoder) {
    var nsResult: [String: [String]] = [:]
    for (key, value) in result {
        nsResult[key.rawValue] = value
    }
    aCoder.encode(nsResult, forKey: "result")
    //...
}
required init?(coder aDecoder: NSCoder) {
    let nsResult = aDecoder.decodeObject(forKey: "result") as! [String: [String]]
    self.result = [:]
    for (nsKey, value) in nsResult {
        self.result[Direction(rawValue: nsKey)!] = value
    }
    //...
}
OOPer
  • 47,149
  • 6
  • 107
  • 142
  • What if my set is in this structure: [AnotherEnumType: [Direction: [String]]] Why I failed to write var nsResult: [String: [String:[Tile]]] = [:[:[Tile]]] – user6539552 Dec 28 '16 at 20:14
  • @user6539552, please edit your question and show more concrete example with specifying how `AnotherEnumType` and `Tile` are defined. – OOPer Dec 28 '16 at 20:26