8

Before Swift 3, you decode boolean values with NSCoder like this:

if let value = aDecoder.decodeObjectForKey(TestKey) as? Bool {
   test = value
}

The suggested approach in Swift 3 is to use this instead:

aDecoder.decodeBool(forKey: TestKey)

But the class reference for decodeBool doesn't explain how to handle the situation if the value you're decoding isn't actually a boolean. You can't embed decodeBool in a let statement because the return value isn't an optional.

How do you safely decode values in Swift 3?

Crashalot
  • 33,605
  • 61
  • 269
  • 439
  • If not boolean provided to aDecoder.decodeBool , it raises the error, as it awaits Boolean only. So you have to be sure it is Bool, haven't you? – pedrouan Sep 23 '16 at 08:38
  • right, so it's not a safe way to check @pedrouan. the error would get caught with the swift 2 syntax. – Crashalot Sep 23 '16 at 08:50
  • You have to know which type you are encoding. This is a bit difficult in some cases especially because `Bool` is encoded as `Bool` while `Bool?` is encoded as `Object`. See http://stackoverflow.com/questions/38072295/fail-to-decode-int-with-nscoder-in-swift. – Sulthan Jan 21 '17 at 16:35

2 Answers2

9

Took me a long time to figure out but you can still decode values like this. The problem I had with swift3 is the renaming of the encoding methods:

// swift2:
coder.encodeObject(Any?, forKey:String)
coder.encodeBool(Bool, forKey:String)

// swift3:
coder.encode(Any?, forKey: String)
coder.encode(Bool, forKey: String)

So when you encode a boolean with coder.encode(boolenValue, forKey: "myBool") you have to decode it with decodeBool but when you encode it like this:

let booleanValue = true
coder.encode(booleanValue as Any, forKey: "myBool")

you can still decode it like this:

if let value = coder.decodeObject(forKey: "myBool") as? Bool {
   test = value
}
errnesto
  • 822
  • 5
  • 15
6

This is safe (for shorter code using nil-coalescing op.) when wanted to use suggested decodeBool.

let value = aDecoder.decodeObject(forKey: TestKey) as? Bool ?? aDecoder.decodeBool(forKey: TestKey)

Using decodeBool is possible in situations when sure that it's Bool, IMO.

pedrouan
  • 12,762
  • 3
  • 58
  • 74
  • `TestKey` is the key (and not the value) and is always of type *String*. Most likely, it's even a string constant. So the decoding will never be executed. You're testing the wrong thing. – Codo Sep 23 '16 at 09:00
  • @Codo can you elaborate please? TestKey is a string constant. Also do you know the safe way to decode values in Swift 3? – Crashalot Sep 23 '16 at 21:17
  • 1
    My comment was referring to the original version of the answer, which was completely different from the current one. – Codo Sep 24 '16 at 09:37