【发布时间】:2018-01-06 14:25:05
【问题描述】:
当我使用 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)"
}
testA 按预期工作。变量为零,因此条件为假。
testB 与预期不同。变量为 nil,如 print 调用所示。但是条件testB != nil 的计算结果为真。为什么会这样?
testCstrong> 也让我感到困惑,因为它是 testC = testB = testA。那么为什么它的行为应该与 testA 不同呢?
我需要如何编写 if 条件 if testB ... 和 if testC ... 才能不为真。
我正在寻找一种不需要我知道类型的解决方案,比如...
if let testB = testB as String
编辑:我正在 Xcode 9.1 Playground 文件中使用 Swift 4 对此进行测试。
编辑2:
有关我要解决的实际问题的一些信息。
我得到了一个由 JSON 解析器创建的 [String: Any?] 类型的字典。我想检查给定键的值是否为 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)
}
【问题讨论】:
-
奇怪的是,
let testB: Any = testA as Any首先没有给出任何编译器错误。testA是可选的,testB不是,因此将testA分配给testB至少应该告诉您这样做不安全,您需要使用as?或as!进行转换。 -
let testB: Any = testA应该警告您可选类型的侵蚀(然后您通过说as Any使其静音)。基本上,您在这里处理的根本问题是,除非编译器知道它是可选的,否则您不能将其视为可选的。说let testC: Any? = testB只会使编译器隐式地将testB包装在另一层可选性中。您要在这里解决的实际问题是什么? -
@florieger 啊,在这种情况下,你只想打开两次。
if let value = dict["key"]为您提供value类型的Any?,这意味着字典具有该值。如果你然后说if let nonNilValue = value,你会得到一个Any,这意味着值本身不是零。您也可以说dict["key"] ?? nil将两层可选性浓缩为一层。比较stackoverflow.com/q/29299727/2976878、stackoverflow.com/q/33049246/2976878 -
相关:Is it possible to cast Any to an Optional? - 您的
testB不是可选的,需要反射才能再次“提取”可选。 -
继 @MartinR 所写的内容(专注于人为的例子);也可能对the following Q&A 感兴趣,关于使用运行时自省来查询
Any实例是否包装了任何类型的Optional<...>实例。
标签: swift