swift - 如何将 nil 作为可选泛型函数参数传递

标签 swift generics option-type

我有一个功能如下:

func request<D: Decodable>(from urlString: String,
                           useToken: Bool = false,
                           requestType: RequestType = .get,
                           body: Data? = nil,
                           expecting type: D.Type? = nil,
                           completion: @escaping (Result<D?>) -> Void)

是否可以这样做:request(..., expecting: nil)func request<D: Decodable>(... expecting type: D.Type? = nil)

我认为我已经达到了如何使用泛型的限制,因为当我这样做时,我得到的编译错误与我正在处理的代码完全无关,所以我认为编译器可能会感到困惑.

当我使用该功能时,如:request(from: "https:..", requestType: .post, body: body) ,编译器提示 Enum element 'post' cannot be referenced as an instance member

我的一些 API 请求不会在正文中返回任何内容,因此我试图找到一种方法来使用我设置的通用函数来表达这一点

最佳答案

这里的根本问题是,您想要的类型是 Void,但 Void 不是可解码的,并且您不能将其设为可解码,因为非名义类型(如 Void)无法扩展。这只是 Swift 当前的限制。

正确的解决方案是重载。创建两个方法:

// For values
func request<D: Decodable>(from urlString: String,
                           useToken: Bool = false,
                           requestType: RequestType = .get,
                           body: Data? = nil,
                           expecting type: D.Type,
                           completion: @escaping (Result<D>) -> Void) {}

// For non-values
func request(from urlString: String,
             useToken: Bool = false,
             requestType: RequestType = .get,
             body: Data? = nil,
             completion: @escaping (Error?) -> Void) {}

创建另一个共享方法,将请求转换为数据并且两者都可以调用:

func requestData(from urlString: String,
                 useToken: Bool = false,
                 requestType: RequestType = .get,
                 body: Data? = nil,
                 completion: @escaping (Result<Data>) -> Void) {}

您的解码请求函数现在将转换 .success(Data)进入D 。您的非解码请求函数将丢弃数据(或者如果您对此很迂腐,可能会确保它是空的),并调用完成处理程序。

如果您希望代码更加并行,以便它始终传递结果而不是错误?,那么您仍然可以通过调整签名来实现:

func request(from urlString: String,
             useToken: Bool = false,
             requestType: RequestType = .get,
             body: Data? = nil,
             completion: @escaping (Result<Void>) -> Void) {}

但是重载仍然是这里的答案。

<小时/>

(旧答案) 通过nil没有问题在这里,只要D可以以某种方式推断出来。但必须有一种方法来推断 D 。例如,以下内容应该没问题:

request(from: "") { (result: Result<Bool?>) in
    print(result)
}

不太好的情况是:

request(from: "") { (result) in
    print(result)
}

因为在这种情况下,无法确定D是什么。是。

也就是说,考虑到您的目标,您不需要 Type无论如何都是可选的。正如你所说,有时结果是“什么也没返回”。 “不返回任何内容”的正确类型是 Void ,不是零。

func request<D: Decodable>(from urlString: String,
                           useToken: Bool = false,
                           body: Data? = nil,
                           expecting type: D.Type = Void.self, // <<----
                           completion: @escaping (Result<D>) -> Void)

(我假设您想要 Result<D> 而不是 Result<D?> ,但根据您的具体用例,两者都可能是正确的。)

Void是 Swift 中的普通类型。它是一种只有一个值的类型:() ,空元组。

关于swift - 如何将 nil 作为可选泛型函数参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52598491/

相关文章:

ios - Facebook自定义登录按钮swift 3 : bug

json - 如何将 JSON 元素与 alamofire 一起使用

ios - 如何在通用中返回闭包

Java Hadoop 与 ChainMapper 泛型的问题

json - 使用 AnyObject 初始化 Swift 类?从 NSJSON 序列化

swift - 无法为 SELECT 命令绑定(bind) sqlite 语句

ios - 在 iOS 设备中启动 YouTube 应用程序

c# - 为什么自定义类型属性不能在泛型中继承?

swift - 检查对象中的任何属性是否为 nil - Swift 3

java - 供应商<X>和供应商<有什么区别?延伸X>