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 您最终在字典中使用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”). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |