IUO在Swift 4.2中作为字典键

时间:2018-08-20 12:02:38

标签: swift swift4.2

以下代码在Swift 4.2(Xcode 10)中的行为不再与在Swift 4.1(Xcode 9.4.1)中的行为相同:

std::bit_cast

在Swift 4.1中,let key: String! = "key" let dict: [AnyHashable:Any]? = ["key":"value"] let val = dict?[key] 接收字典值(“值”),而在Swift 4.2中则为零。

如果我删除了明显地解包的可选(IUO),或者将字典声明为val,那么问题就消失了,所以两者都

[String:Any]

let key: String = "key"
let dict: [AnyHashable:Any]? = ["key":"value"]
let val = dict?[key]

导致let key: String! = "key" let dict: [String:Any]? = ["key":"value"] let val = dict?[key] 最终包含字符串“ value”。

这是Swift 4.2中的预期行为,还是编译器错误?

请问一下,我有一个庞大的代码库,其中的键和字典都来自于Objective-C代码,该代码有点难以更改。因此,我想知道这种行为变化是否是永久的,应该开始更新使用此模式的代码中的许多位置,还是等到发布稳定的Xcode 10版本之后。

1 个答案:

答案 0 :(得分:4)

有一个提案SE-0054,已在Swift 4.2中完全实现。过去,ImplicitlyUnwrappedOptional类型的功能不同于Swift 4.2(现在,所有IUO都是Swift 4.2中的Optional类型,而不是ImplicitlyUnwrappedOptional)。

从提案(重点是我的):

  

如果可以显式对表达式进行强类型检查   可选类型,它将是。但是,类型检查器将退回到   必要时强制使用可选。这种行为的后果是   引用声明为T的值的任何表达式的结果!   将是T型还是T?型。例如,在下面   代码:

let x: Int! = 5
let y = x
let z = x + 0
     

…x被声明为IUO,但是   因为y类型的初始值设定项可正确检查为可选项y   将绑定为Int类型。但是,z的初始化器不   用x声明为可选的类型检查(没有+的重载   需要一个可选的),因此编译器强制使用可选和类型   将初始化程序检查为Int。

在您的情况下,key变量被推断为String?类型,因此您仍然必须强制转换它。该代码将起作用:

let val = dict?[key!]

val的值为Optional("value")

关于[String:Any]起作用的原因,根据引号中强调的部分,String?不能用在String上,因此编译器将强制对其进行解包(必须使它会编译)。