可选绑定评估可选(nil)的不需要的行为
Unwanted behaviour with optional binding evaluating 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
并且转换也是 return nil
所以 else
块被执行。
在 xCode 10 和 Swift 4.2 中,我有以下日志:
0 - values[langCode!] = null
1 - values[langCode!] as? T = Optional(nil)
2 - value to return= nil
即使 values[langCode!] 为 "null".
,也会执行 if let
代码块
一个区别是 swift 4.2 values[langCode!] as? T
是 Optional(nil)
而 Swift 4.1 values[langCode!] as? T
是 nil
.
我检查了 version 4.2 的变更日志,但我看不到可以解释该行为的内容,我还检查了 JSONSerialization(用于序列化 json 文件)没有进行任何更改
有人在切换到 Swift4.2 时也遇到过这种情况吗?
有人有解释吗?还有解决方法?
在这种代码中使用可选绑定有什么好处?写 if (values[langCode!] != nil) {...
而不是可选绑定会不好吗?
谢谢
如果您没有更改代码并且它的行为有所不同,那么这可能是 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)")
如果它在 Swift 4.1 下打印 Int
(或其他),在 Swift 4.2 下打印 Optional<Int>
,那就是问题所在。
我回答我的问题,因为评论中给出了正确答案。
Swift4.1 和 Swift4.2 之间观察到的差异是由于有意更改所致。 @Hamish 在这里解释了答案中的所有内容:
将 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
并且转换也是 return nil
所以 else
块被执行。
在 xCode 10 和 Swift 4.2 中,我有以下日志:
0 - values[langCode!] = null
1 - values[langCode!] as? T = Optional(nil)
2 - value to return= nil
即使 values[langCode!] 为 "null".
,也会执行if let
代码块
一个区别是 swift 4.2 values[langCode!] as? T
是 Optional(nil)
而 Swift 4.1 values[langCode!] as? T
是 nil
.
我检查了 version 4.2 的变更日志,但我看不到可以解释该行为的内容,我还检查了 JSONSerialization(用于序列化 json 文件)没有进行任何更改
有人在切换到 Swift4.2 时也遇到过这种情况吗? 有人有解释吗?还有解决方法?
在这种代码中使用可选绑定有什么好处?写 if (values[langCode!] != nil) {...
而不是可选绑定会不好吗?
谢谢
如果您没有更改代码并且它的行为有所不同,那么这可能是 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)")
如果它在 Swift 4.1 下打印 Int
(或其他),在 Swift 4.2 下打印 Optional<Int>
,那就是问题所在。
我回答我的问题,因为评论中给出了正确答案。
Swift4.1 和 Swift4.2 之间观察到的差异是由于有意更改所致。 @Hamish 在这里解释了答案中的所有内容: