为什么在类型为 [String : Any] 的字典中隐式解包的可选不解包 [英] Why does implicitly unwrapped optional not unwrap in dictionary of type [String : Any]

查看:40
本文介绍了为什么在类型为 [String : Any] 的字典中隐式解包的可选不解包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在我的类中声明了一个隐式解包的可选项,然后我在 [String : Any] 类型的 Dictionary 中引用它,它不会被解包.为什么是这样?为什么不是可选的 Any 不强制解包?

If I have an implicitly unwrapped optional declared in my class which I then reference in a Dictionary of type [String : Any], it doesn't get unwrapped. Why is this? Why does Any, which isn't optional, not force it to unwrap?

var aString: String! = "hello"
var params : [String : Any] = [
    "myString" : aString
]
print(params)
// This prints ["myString": Swift.ImplicitlyUnwrappedOptional<Swift.String>.some("hello")]

请注意,如果我将字典指定为 [String : String] 类型,它将被解包,但这在我的 Dictionary<中需要多种类型时没有用/代码>.

Note that if I specify the dictionary to be of type [String : String], it will be unwrapped, but this is not useful for when I need multiple types in my Dictionary.

推荐答案

根据 SE-0054,IUO 仅在需要其解包类型的上下文中强制解包.在您的情况下,IUO 不需要强制解包以强制为 Any(因为 Any 可以表示任何值),所以它不是.

Under the rules set out by SE-0054, IUOs are only force unwrapped in contexts that demand their unwrapped type. In your case, the IUO doesn't need to be force unwrapped in order to be coerced to Any (as Any can represent any value), so it isn't.

在这些问答中更详细地讨论了这种行为:

This behaviour is discussed in more detail in these Q&As:

你在字典中得到一个 ImplicitlyUnwrappedOptional 值的事实是在最新的 Swift 快照中已经被删除的遗留行为,将来你将得到一个 Optional 值(因为 IUO 不再是一种类型).

The fact that you end up with an ImplicitlyUnwrappedOptional value in your dictionary is legacy behaviour that has been removed in the latest Swift snapshots, in the future you will end up with an Optional value instead (as IUO is no longer a type).

然而,这里需要注意的一件重要事情(我肯定会绊倒人们)是 IUO 的印刷在 4.1 中发生了变化.

One important thing to note here however (that I'm sure will trip up people) is that the printing of IUOs got changed in 4.1.

在 Swift 4.0.3 中,您的示例打印如下:

In Swift 4.0.3, your example prints like this:

var aString: String! = "hello"
var params : [String : Any] = [
  "myString" : aString
]
print(params)
// This prints ["myString": hello]

给您一种错觉,即 IUO 在被强制为 Any 时被强制解包.然而,这正是 Swift 4.0.3 中 IUO 的打印方式——如果它们有一个值,那么它们将打印为该值,否则它们将打印为 nil:

giving you the illusion that the IUO was force unwrapped when coerced to Any. This however is just how IUOs were printed in Swift 4.0.3 – if they had a value, then they would print as that value, otherwise they would print as nil:

var aString: String! = nil
var params : [String : Any] = [
  "myString" : aString
]
print(params)
// This prints ["myString": nil]

这在 Swift 4.1 中发生变化的原因是 ImplicitlyUnwrappedOptionalCustom(Debug)StringConvertible 的一致性被删除了 在本次提交中,以便在删除类型本身方面取得进展.所以现在 ImplicitlyUnwrappedOptional 值使用 Swift 的默认打印机制(使用反射)打印.

The reason why this changed in Swift 4.1 is that ImplicitlyUnwrappedOptional's conformance to Custom(Debug)StringConvertible was removed in this commit in order to make progress towards removing the type itself. So now ImplicitlyUnwrappedOptional values get printed using Swift's default printing mechanism (using reflection).

因此,在字典中,您将获得 IUO 的默认 debugDescription,如下所示:

So, in a dictionary, you get the IUO's default debugDescription, which looks like this:

let aString: String! = "hello"
let params : [String : Any] = [
  "myString" : aString
]
print(params)
// This prints ["myString": Swift.ImplicitlyUnwrappedOptional<Swift.String>.some("hello")]

如果你自己打印它,你会得到它的默认description,看起来像这样:

If you had printed it on its own, you would get its default description, which looks like this:

let aString: String! = "hello"
print(aString) // some("hello")

这是因为在 Swift 4.1 中,ImplicitlyUnwrappedOptional 类型的实现方式与 Optional 相同,枚举有两种情况:

This is because in Swift 4.1, the ImplicitlyUnwrappedOptional type is implemented in the same way as Optional, an enumeration with two cases:

public enum ImplicitlyUnwrappedOptional<Wrapped> : ExpressibleByNilLiteral {
  // The compiler has special knowledge of the existence of
  // `ImplicitlyUnwrappedOptional<Wrapped>`, but always interacts with it using
  // the library intrinsics below.

  /// The absence of a value. Typically written using the nil literal, `nil`.
  case none

  /// The presence of a value, stored as `Wrapped`.
  case some(Wrapped)

  // ...
}

对于带有有效载荷值的 IUO,Swift 的默认反射因此会将其打印为包含包装值的 some 案例.

For an IUO with a payload value, Swift's default reflection will therefore print it as the case some containing the wrapped value.

但这只是暂时的;IUO 类型目前(在 Swift 4.1 中)已弃用,但它将在 Swift 4.2 中删除.编译器在很多地方内部使用了 IOU 类型,这需要 相当多的工作才能删除.因此,在 4.2 中,您的字典中将具有 actual Optional 值,其打印方式类似于 Optional("hello").

But this is only temporary; the IUO type is currently (in Swift 4.1) deprecated, however it will be removed in Swift 4.2. The compiler was internally using the IUO type in quite a few places, which took quite a bit of work to remove. Therefore in 4.2 you'll have actual Optional values in your dictionary, which will print like Optional("hello").

这篇关于为什么在类型为 [String : Any] 的字典中隐式解包的可选不解包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆