Hello, I have a question on using dictionary with optional type value. Take a look at this code please.
// Swift 4.2
var dict: [String: Int?] = ["a": 1]
do {
dict["a"] = Optional<Int>.none
print(dict.count) // 1 (Optional value is set)
}
dict["a"] = 1 // set it back.
do {
dict["a"] = .none
print(dict.count) // 0 (Value is removed)
}
As you can see, setting .none
removes the value while Optional<Int>.none
does not. That means I cannot just simply omit the long type name believing that the compiler would infer what I intended.
I guess .none
is regarded same as nil
but I think those two cases should behave in the same way. Otherwise it would be very easy to misuse.
You can also use .some(nil)
or .some(.none)
instead of Optional<Int>.none
.
If you're assigning to a dictionary subscript expression:
dict["a"] = …
use an expression of the value type to replace the existing value:
dict["a"] = nil as Int? // replaces
To remove the existing value, use an expression of the value type with an extra level of optionality, so:
dict["a"] = nil as Int?? // removes
Now, normal compiler inference can deduce the type of the RHS from the type of the LHS, so the second of these can be simplified:
dict["a"] = nil // removes, nil inferred to be of type 'Int??'
That gives you a nice dichotomy:
dict["a"] = nil as Int? // replaces
dict["a"] = nil // removes
which you can just learn as a rule of thumb for value types that are optionals.
3 Likes
You can also use the sugared version of Optional<Int>
– Int?
. For example:
dict["a"] = Int?.none
Or alternatively use updateValue(_:forKey:)
which can only replace, and not remove, values:
dict.updateValue(nil, forKey: "a")
Though generally, I would advise against using dictionaries with optional Value
types – IMO it's far too easy to shoot yourself in the foot with doubly wrapped optionals.
2 Likes