ImplicitlyUnwrappedOptional in init vs later

2019-04-08 16:42发布

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")]

标签: swift swift4
1条回答
我欲成王,谁敢阻挡
2楼-- · 2019-04-08 17:16

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:

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.

查看更多
登录 后发表回答