I would like to understand why I don't get ImplicitlyUnwrappedOptional
when I do params["bar"] = str
but I get it when I declare params
with the same force unwrapped variable.
See the playground below:
import UIKit
var str: String!
str = "Hello"
var params: [String: Any] = [
"foo": str
]
params["bar"] = str
print(params)
// ["bar": "Hello", "foo": Swift.ImplicitlyUnwrappedOptional<Swift.String>.some("Hello")]
In Swift 4.1, when you do:
var str: String!
str = "Hello"
var params: [String: Any] = [
"foo": str
]
The ImplicitlyUnwrappedOptional
(IUO) value is coerced to Any
, which is why it appears as an IUO inside your dictionary. It won't be force unwrapped, because the compiler will only force unwrap an IUO when the context demands its unwrapped type, which isn't the case with Any
.
However the fact that you end up with an ImplicitlyUnwrappedOptional
value is legacy behaviour. With the removal of the IUO type in Swift 4.2, you'll get an Optional
value inside your dictionary instead, which will print as Optional("Hello")
.
There's more discussion of the above behaviour in this Q&A:
- Why does implicitly unwrapped optional not unwrap in dictionary of type [String : Any]
When you do:
params["bar"] = str
You're using Dictionary
's subscript(key: Key) -> Value?
, which takes an Optional
value – performing a removal if nil
is passed, otherwise doing an insertion of the unwrapped value.
- In Swift 4.1, the IUO value
str
will be implicitly converted to an Optional
which can then be passed to the subscript.
- In Swift 4.2, the IUO type has been removed, so
str
already is an Optional
, which can be passed straight to the subscript without any intermediate conversions.
In both cases, str
's unwrapped value is inserted into the dictionary, which is why you see it as being unwrapped. If str
had been nil
, no value for the key "bar"
would have been inserted.