首页 > 解决方案 > 可选绑定评估 optional(nil) 的不良行为

问题描述

将 xCode 更新到版本 10(和 swift 4.2)后,我对可选绑定有一个奇怪的行为

代码如下,它是关于读取 json 文件的,T是一个泛型类型(这里String

// Are there values for configName ?
if let values = cfg[configName] as? [String: Any] {

    print("0 - values[langCode!] = ", values[langCode!] ?? "null")
    print("1 - values[langCode!] as? T = ", values[langCode!] as? T)

    // is there a value for langCode ?
    if let value = values[langCode!] as? T {
        print("2 - value to return= ", value)
        return value
    } else {
        print("3 - Do something else ")
    }
}

在 xCode 9.4.1 和 Swift 4.1 中,我有以下日志:

0 - values[langCode!] =  null
1 - values[langCode!] as? T =  nil
3 - Do something else 

这就是我想要的,values[langCode!]并且nil演员也返回nil,所以else块被执行。

在带有 Swift 4.2 的 xCode 10 中,我有以下日志:

0 - values[langCode!] =  null
1 - values[langCode!] as? T =  Optional(nil)
2 - value to return=  nil

if let即使 values[langCode!] 为“null”,这里也会执行该块。

一个区别是 swift 4.2values[langCode!] as? T是 anOptional(nil)而 Swift 4.1values[langCode!] as? Tnil.

我检查了4.2 版的更改日志,但看不到可以解释该行为的内容,我还检查了 JSONSerialization 没有进行任何更改(用于序列化 json 文件)

有人在切换到 Swift4.2 时也经历过这种事情吗?有人有解释吗?和解决方法?

在这种代码中,使用可选绑定有什么好处?if (values[langCode!] != nil) {...写而不是可选绑定会很糟糕吗?

谢谢

标签: swiftxcode10ios12swift4.2optional-binding

解决方案


如果您没有更改代码并且它的行为有所不同,那么这可能是 Swift 中的一个错误。如果你能做一个小测试用例,你应该在https://bugs.swift.org提交一个错误。

无论如何,听起来在 Swift 4.1 中,Swift 将类型推断T为某种非Optional类型(例如Int),而在 Swift 4.2 中,Swift 将 T 推断为Optional(例如Int?)。您可以通过添加以下语句进行检查:

print("Type T is bound to \(T.self)")

如果它Int在 Swift 4.1 和 Swift 4.2 下打印(或其他)Optional<Int>,那就是问题所在。


推荐阅读