1

Given the dictionary of dictionary below, what is the correct syntax to unwrap the Int? in one step?

let dict:Dictionary<String, Dictionary<String, Int?>> = [
"parentKey" : [
    "firstKey" : 1,
    "secondKey" : nil]
]

let x = "someKey"
let y = "someOtherKey"
var foo = 0

if let goo = dict[x]?[y] { foo = goo } //<-- Error: cannot assign (Int?) to Int

if let goo = dict[x]?[y], let boo = goo { foo = boo } //<-- OK

In the first 'if let', goo is returned as an Int? - goo then needs to be unwrapped as in the second 'if let'...

What is the correct syntax for doing this in one step?

Andrew Coad
  • 297
  • 2
  • 13
  • `if let goo = dict[x]?[y] ?? NSNotFound { foo = goo }` ? – Michael Dautermann Nov 23 '18 at 04:32
  • This gives the correct result when both keys are valid (e.g. x = "parentKey, y = "firstKey" or y = "secondKey". However, it gives an incorrect result when either x or y is a non-existent key (e.g. x = "someKey" or y = "someOtherKey") – Andrew Coad Dec 01 '18 at 05:11

3 Answers3

1

Use nil colesecing and provide a default value. Only way to safely unwrap a dictionary value.

if let goo = dict[x]?[y] ?? NSNotFound { foo = goo }  
SirCJ
  • 505
  • 6
  • 11
1

As far as I understood you want to force unwrap a double optional. There different methods.

let dbOpt = dict[x]?[y]

My favorite:

if let goo = dbOpt ?? nil { foo = goo } 

Using flatMap:

if let goo = dbOpt.flatMap{$0} { foo = goo } 

Using pattern matching:

if case let goo?? = dbOpt { foo = goo }
Andrea
  • 26,120
  • 10
  • 85
  • 131
0

There are many ways to do this but one of the simplest solution available is :

var foo = 0

if let goo = dict[x]?[y]  as? Int{
    foo = goo
}
print(foo)
nikksindia
  • 1,147
  • 1
  • 10
  • 18