0

let say I defined a class

class Dummy {

    var title: String?
}

and I have a dictionary as

let foo: [Int: String?]  = [:]

then when I make an assignment as below

var dummy = Dummy()

dummy.title = foo[1]

it says

Cannot assign value of type 'String??' to type 'String?'

Insert ' as! String'

return type of foo is String? and Dictionary returns optional of its value type when used subscript but what is String?? type in swift?

I think it should be legal to make such assignment. Why it complains and how should I make this assignment

Community
  • 1
  • 1
plymr
  • 45
  • 7
  • Compare [Two (or more) optionals in Swift](https://stackoverflow.com/q/27225232/1187415). – Martin R Jun 16 '20 at 11:00
  • 1
    You defined the value type as an optional, therefore there is a difference between “the dictionary does not have a value for that key” and “the dictionary value for that key exists and is nil”. I demonstrated the difference in my answer to the above mentioned Q&A. – Martin R Jun 16 '20 at 11:02
  • Also related: [Check if key exists in dictionary of type `[Type:Type?]`](https://stackoverflow.com/q/29299727/1187415). – Martin R Jun 16 '20 at 11:06

2 Answers2

0

Since having a value corresponding to the key 1 in the dictionary foo is optional and the value in the dictionary is of type String? it returns type String??. Unwrapping the value once to check if the value exists would fix this issue

if let value = foo[1] {
    dummy.title = value
}
Frankenstein
  • 15,732
  • 4
  • 22
  • 47
0

By declaring your dictionary as [Int:String?] you are saying that the key is an Int and values are optional Strings. Now the key may not be present in the dictionary, so foo[1] optionally returns an optional and you end up with an with an optional optional - String??

Now while there are sometimes uses for optional optionals, I don't think that is what you want in this case.

You can simply make a dictionary of [Int:String] and then not insert an element if the value is nil.

let foo: [Int: String]  = [:]
dummy.title = foo[1]

If you do need to handle the case where "there is a value for this key and it is nil" then the nil-coalescing operator may help you:

dummy.title = foo[1] ?? nil

or even

dummy.title = foo[1] ?? ""
Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • Class and variables in this question are demonstration purpose, in my actual case, it is not same to having a key in dictionary and value equals to `nil` and not having the key in dictionary, but in some cases it does not matter. I tought swift could convert `Optional>.none` to `Optional.none` – plymr Jun 16 '20 at 11:13
  • 1
    No, there is clearly a semantic difference between "there is no value for this key" and "there is a value for this key and it is `nil`" – Paulw11 Jun 16 '20 at 11:14