我有一个功能如下:
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/