Swift5.4 中可选的误报
False positive on optional in Swift5.4
我有一个字典扩展,在 Xcode 12.5 和 Swift 5.4 发布之前一直运行良好。
问题是在 Swift5.4 中似乎有一个更改,使可选的可选 return 成为误报。在某种程度上它确实有意义但是现在我的扩展失败了。
考虑以下示例代码:
let dictionary: [String: Any] = ["foo": "bar"]
if let foo = dictionary["foo"] as? String? {
debugPrint("Foo exists")
}
if let bar = dictionary["bar"] as? String? {
debugPrint("bar exists")
}
在 Swift 5.4 之前,这将导致以下结果:
"Foo exists"
但是现在在 Swift 5.4 中我得到以下结果:
"Foo exists"
"bar exists"
这是因为即使字典定义为 [String: Any]
,String?
符合类型 Any
,因此 nil
符合 any
所以 if 情况会触发,因为 nil 是 any。
对我来说,这给我使用的 require 函数带来了问题,如果通用类型设置为可选,该函数就会触发。我的分机:
enum DictionaryExtractionError: Error {
case missingProperty(String), casting(String)
}
extension Dictionary where Key == String, Value == Any {
func require<T>(_ name: String) throws -> T {
if let prop = self[name] as? T, (prop as Any?) != nil {
return prop
}
throw self[name] == nil ? DictionaryExtractionError.missingProperty(name) : DictionaryExtractionError.casting(name)
}
func require<T>(_ name: String, fallback: T) -> T {
do {
return try require(name) ?? fallback
} catch {
return fallback
}
}
}
let dictionary: [String: Any] = ["fooBar": "barFoo"]
let valid: String = dictionary.require("fooBar", fallback: "no Foobar")
let validMissing: String = dictionary.require("doesntExist", fallback: "no Foobar")
let inValidMissing: String? = dictionary.require("doesntExist", fallback: "no Foobar")
debugPrint(valid) // Should return: "barFoo"
debugPrint(validMissing) // Should return: "no Foobar"
debugPrint(inValidMissing) // Should return: Optional("no Foobar") <<<<<< This one is wrong
我的问题:有什么方法可以检查 T
是否为可选类型?如果是这样,我可以调整我的代码来检查通用类型在哪里是可选的,确保 prop
不是 nil。
您的示例代码也在 Xcode 12.4 中打印 "bar exists"
。
无论如何,试试这个 require
的实现:
func require<T>(_ name: String) throws -> T {
guard let index = self.index(forKey: name) else {
throw DictionaryExtractionError.missingProperty(name)
}
guard let t = self[index].value as? T else {
throw DictionaryExtractionError.casting(name)
}
return t
}
我有一个字典扩展,在 Xcode 12.5 和 Swift 5.4 发布之前一直运行良好。 问题是在 Swift5.4 中似乎有一个更改,使可选的可选 return 成为误报。在某种程度上它确实有意义但是现在我的扩展失败了。
考虑以下示例代码:
let dictionary: [String: Any] = ["foo": "bar"]
if let foo = dictionary["foo"] as? String? {
debugPrint("Foo exists")
}
if let bar = dictionary["bar"] as? String? {
debugPrint("bar exists")
}
在 Swift 5.4 之前,这将导致以下结果:
"Foo exists"
但是现在在 Swift 5.4 中我得到以下结果:
"Foo exists"
"bar exists"
这是因为即使字典定义为 [String: Any]
,String?
符合类型 Any
,因此 nil
符合 any
所以 if 情况会触发,因为 nil 是 any。
对我来说,这给我使用的 require 函数带来了问题,如果通用类型设置为可选,该函数就会触发。我的分机:
enum DictionaryExtractionError: Error {
case missingProperty(String), casting(String)
}
extension Dictionary where Key == String, Value == Any {
func require<T>(_ name: String) throws -> T {
if let prop = self[name] as? T, (prop as Any?) != nil {
return prop
}
throw self[name] == nil ? DictionaryExtractionError.missingProperty(name) : DictionaryExtractionError.casting(name)
}
func require<T>(_ name: String, fallback: T) -> T {
do {
return try require(name) ?? fallback
} catch {
return fallback
}
}
}
let dictionary: [String: Any] = ["fooBar": "barFoo"]
let valid: String = dictionary.require("fooBar", fallback: "no Foobar")
let validMissing: String = dictionary.require("doesntExist", fallback: "no Foobar")
let inValidMissing: String? = dictionary.require("doesntExist", fallback: "no Foobar")
debugPrint(valid) // Should return: "barFoo"
debugPrint(validMissing) // Should return: "no Foobar"
debugPrint(inValidMissing) // Should return: Optional("no Foobar") <<<<<< This one is wrong
我的问题:有什么方法可以检查 T
是否为可选类型?如果是这样,我可以调整我的代码来检查通用类型在哪里是可选的,确保 prop
不是 nil。
您的示例代码也在 Xcode 12.4 中打印 "bar exists"
。
无论如何,试试这个 require
的实现:
func require<T>(_ name: String) throws -> T {
guard let index = self.index(forKey: name) else {
throw DictionaryExtractionError.missingProperty(name)
}
guard let t = self[index].value as? T else {
throw DictionaryExtractionError.casting(name)
}
return t
}