微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

swift – 为什么隐式解包可选不在字典中解包[String:Any]

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

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

请注意,如果我将字典指定为[String:String]类型,它将被解包,但是当我在Dictionary中需要多个类型时,这没有用.

解决方法

根据 SE-0054规定的规则,IUO仅在需要其未打包类型的环境中展开.在您的情况下,IUO不需要强制解包以便被强制转换为Any(因为Any可以表示任何值),所以它不是.

在这些Q& As中更详细地讨论了这种行为:

> Swift 3 incorrect string interpolation with implicitly unwrapped Optionals
> Implicitly unwrapped optional assign in Xcode 8

您最终在字典中使用ImplicitlyUnwrappedOptional值的事实是在最新的Swift快照中已删除的遗留行为,将来您将最终使用Optional值(因为IUO不再是类型).

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

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

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

给你的幻觉是IUO在强迫任意时被强行打开.然而,这只是如何在Swift 4.0.3中打印IUO – 如果它们有一个值,那么它们将打印为该值,否则它们将打印为零:

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

之所以在Swift 4.1中发生这种变化,是因为ImplicitlyUnwrappedOptional对Custom(Debug)StringConvertible的一致性被删除in this commit,以便在删除类型本身方面取得进展.所以现在使用Swift的认打印机制(使用反射)打印ImplicitlyUnwrappedOptional值.

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

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

如果你自己打印它,你会得到它的认描述,如下所示:

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

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

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的认反射因此会将其打印为包含包装值的情况.

但这只是暂时的; IUO类型目前(在Swift 4.1中)已被弃用,但它将在Swift 4.2中删除.编译器在很多地方内部使用了IUO类型,占用了quite a bit of work to remove.因此在4.2中,您将在字典中拥有实际的可选值,它将打印为Optional(“hello”).

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐