Nil检查并不总是在Swift中为Any工作

flo*_*ger 9 swift

当我使用Any类型时,我对Swift如何检查nil感到困惑.
这是一个例子:

let testA: Any? = nil
let testB: Any = testA as Any
let testC: Any? = testB

if testA != nil {
    print(testA) // is not called as expected
}
if testB != nil {
    print(testB) // prints "nil"
}
if testC != nil {
    print(testC) // prints "Optional(nil)"
}
Run Code Online (Sandbox Code Playgroud)

testA按预期工作.变量为nil,因此条件为false.

testB的工作并不像预期的那样.变量为nil,如打印调用所示.但条件testB != nil评估为真.为什么会这样?

testC也困惑我,因为它是testC = testB = testA.那么为什么它的行为与testA不同呢?

我怎么需要写if条件if testB ...if testC ...不是真的.
我正在寻找一种不需要我知道类型的解决方案,比如......

if let testB = testB as String
Run Code Online (Sandbox Code Playgroud)

编辑:我正在使用Swift 4在Xcode 9.1 Playground文件中测试它.

Edit2:
关于我想要解决的实际问题的一些信息.我正在获取[String: Any?]由JSON解析器创建的类型字典.我想检查给定键的值是否为nil,但是当键存在且值为Optional(nil)时它不起作用.

例:

var dict = [String: Any?]()
var string = "test"
var optionalString: String?
dict["key1"] = string
dict["key2"] = optionalString

if dict["key2"] != nil {
    print(dict["key2"]) // should not be executed, but returns Optional(nil)
}
Run Code Online (Sandbox Code Playgroud)

Pun*_*rma 3

在 Swift 中,nil 实际上是一个具体的值(枚举类型)。testB它是Any类型,持有enum Optionalwith 值none,因此条件testB != nil为真。

在此输入图像描述

Any这解决了of如何testB能够保持 nil 值的谜团。

谈到您的实际问题,我在 Storyboard(Xcode 9.2)中尝试了这段代码,它按预期工作。

var dict = [String: Any]()
var string = "test"
var optionalString: String?
dict["key1"] = string
dict["key2"] = optionalString

if let value = dict["key2"] {
    print(value) // doesn't get executed
}
Run Code Online (Sandbox Code Playgroud)

对于 testB 和 testC,似乎 == 检查 nil 应该提供一个解决方案,但是,因为二进制操作数不能与两个 Any 一起使用?操作数,我们不能使用==。

但使用 switch-case 能够给出正确的结果:

switch testB {
case Optional<Any>.none:
    print("value is none")
default:
    print("value is not none")
}

switch testC! {
case Optional<Any>.none:
    print("value is none")
default:
    print("value is not none")
}
Run Code Online (Sandbox Code Playgroud)

O/P
值无
值无

  • 正如 /sf/answers/4307147071/ 中所解释的,我认为问题实际上发生在 `(Any) != nil` 中 - 编译时类型 `Any` 的表达式在编译时被包装在“Optional”的另一层中 - 所以“Optional”的第一层是非“nil”,并且它包含一个“Optional”,它是“nil”。(技术上是“.none”。)在运行时,“String?”被包装成“String??”。如果我的评论没有意义,也许可以去阅读链接的答案。 (2认同)