如何在 Swift 5.1 (Xcode 11 Playground) 中为可选项实现泛型和非泛型函数签名的重载?
How can I achieve overloading both generic and non-generic function signatures for optionals in Swift 5.1 (Xcode 11 Playground)?
import Foundation
enum Errors: Error {
case badParse
}
public typealias JSONDictionary = [String: Any]
public func decode(_ dictionary: JSONDictionary, key: String) throws -> URL {
guard let string = dictionary[key] as? String else {
throw Errors.badParse
}
if let url = URL(string: string) {
return url
}
throw Errors.badParse
}
public func decode<T>(_ dictionary: JSONDictionary, key: String) throws -> T {
guard let value = dictionary[key] else {
throw Errors.badParse
}
guard let attribute = value as? T else {
throw Errors.badParse
}
return attribute
}
let url: URL = try decode(["url":"test/url"], key: "url") // url: test/url
let urlOptional: URL? = try? decode(["url":"test/url"], key: "url") // nil
只要您正在解码一个非可选的,上面的代码就可以工作。调用特定的非通用解码函数并构造 URL 。
但是,如果您有一个可选类型的变量并对它进行解码,它将不会使用正确的函数。在 swift 4.2 中,可选项和非可选项都将使用正确的非泛型函数,但自从我更新到 Xcode 11 swift 5.1 后,已经看到了这种行为。
如有任何帮助,我们将不胜感激!
我不想使用可选的 returns 来制作函数签名,例如
public func decode(_ dictionary: JSONDictionary, key: String) throws -> URL? {
因为它不可扩展...而且过去没有它也能正常工作。
显然,类型推断的工作方式在 Swift 5 中发生了一些变化。如果您只是想让它使用正确的重载,您只需要给它一点推动:
let urlOptional: URL? = try? decode(["url":"test/url"], key: "url") as URL
通过在末尾添加 as URL
。
import Foundation
enum Errors: Error {
case badParse
}
public typealias JSONDictionary = [String: Any]
public func decode(_ dictionary: JSONDictionary, key: String) throws -> URL {
guard let string = dictionary[key] as? String else {
throw Errors.badParse
}
if let url = URL(string: string) {
return url
}
throw Errors.badParse
}
public func decode<T>(_ dictionary: JSONDictionary, key: String) throws -> T {
guard let value = dictionary[key] else {
throw Errors.badParse
}
guard let attribute = value as? T else {
throw Errors.badParse
}
return attribute
}
let url: URL = try decode(["url":"test/url"], key: "url") // url: test/url
let urlOptional: URL? = try? decode(["url":"test/url"], key: "url") // nil
只要您正在解码一个非可选的,上面的代码就可以工作。调用特定的非通用解码函数并构造 URL 。
但是,如果您有一个可选类型的变量并对它进行解码,它将不会使用正确的函数。在 swift 4.2 中,可选项和非可选项都将使用正确的非泛型函数,但自从我更新到 Xcode 11 swift 5.1 后,已经看到了这种行为。
如有任何帮助,我们将不胜感激!
我不想使用可选的 returns 来制作函数签名,例如
public func decode(_ dictionary: JSONDictionary, key: String) throws -> URL? {
因为它不可扩展...而且过去没有它也能正常工作。
显然,类型推断的工作方式在 Swift 5 中发生了一些变化。如果您只是想让它使用正确的重载,您只需要给它一点推动:
let urlOptional: URL? = try? decode(["url":"test/url"], key: "url") as URL
通过在末尾添加 as URL
。