我有以下测试在过去几年发布的所有 Xcode 版本中都成功除了 Xcode 12.5 beta 3:
var nilString: String? = nil
var dict: [String: Any] = ["hello": nilString as Any]
var element = dict["hello"] as Any
print(element)
print(type(of: element))
switch element {
case Optional<Any>.none:
print("element is nil")
default:
assertionFailure("element is not nil. wtf?")
}
在 Xcode 12.4 中我打印了这个
Optional(nil)
Optional<Any>
element is nil
在 Xcode 12.5 beta 3 中我打印了这个
Optional(nil)
Optional<Any>
Fatal error: element is not nil. wtf?
有人能解释一下这个问题吗?我现在如何检查 Any 是否为零?它会在候选版本中修复吗?
更新 想要更加困惑吗?
var nilString: String? = nil
var element: Any = nilString as Any
print(element)
print(type(of: element.self))
switch element {
case Optional<Any>.none:
print("element is nil")
default:
assertionFailure("element is not nil")
}
输出:
nil
Optional<String>
element is nil
我想我的 nilString 在放入字典时发生了问题。
答案 0 :(得分:1)
感谢 Jessy 指出 Optional<Any>
内部实际上可能有 some
值并且可能是 nil
。我想出了一个检查 Any 是否为 nil 的函数,它可以在旧的和最新的 Xcode 中工作(在 12.5 beta 3 中肯定已经改变了一些打破旧测试的东西,即将 nil 转换为 Any 到字典值导致要包装到 Optional<Any>.some
中而不是将其视为 Optional<Any>.none
) 的值:
func isOptional(_ instance: Any) -> Bool {
let mirror = Mirror(reflecting: instance)
let style = mirror.displayStyle
return style == .optional
}
func checkIfAnyIsNil(_ v: Any) -> Bool {
if (isOptional(v)) {
switch v {
case Optional<Any>.none:
return true
case Optional<Any>.some(let v):
return checkIfAnyIsNil(v)
default:
return false
}
} else {
return false
}
}
断言:
var nilString: String? = nil
var dict: [String: Any] = ["nilString": nilString as Any]
assert(checkIfAnyIsNil(dict["nilString"] as Any))
assert(checkIfAnyIsNil(nilString as Any))
assert(checkIfAnyIsNil("some string" as Any) == false)