所以我有这个枚举,我用于我在应用程序中使用的几个 url 请求:
enum Netwrok {
case popular
case topRated
case latest
// ...
static let baseUrl = "http://..."
func path() -> String {
switch self {
case .popular: return "/popular"
// ...
}
}
}
我想添加一个函数,该函数返回网络堆栈应用来解码数据的模型的可解码类型。
所以我认为这样的事情可以完成这项工作:
func returnType<T>() -> T.Type where T : Decodable {
switch self {
case .popular:
return Popular.self
// ...
}
}
但我不能让它工作,它说:
无法将类型为"Popular.Type"的返回表达式转换为返回类型"T.Type">
要我强行投T.Type
.
如何创建一个返回可解码的函数,以便可以处理该类型,但 JSONDecoder 的解码函数?
谢谢。
你问的很简单,但可能不是你想要的。您要求做的是返回一个类型。这没有什么通用的。
func returnType<T>() -> T.Type where T : Decodable {
此语法定义由调用方传递的类型参数T
。它不是由你的函数定义的。这意味着调用方可以传递任何可解码的类型,并且您的函数将返回它。例如,调用方可以将T
设置为 Int(因为它是可解码的(,您将返回Int.Type
。这很容易实现(return T.self
(,但不是你的意思。
你的意思是,该函数返回函数知道的某种可解码的类型,但调用方不知道:
func returnType() -> Decodable.Type { ... }
这将正常工作,并且完全符合您的要求,但它表明您可能不正确地构建了此网络堆栈,并且以后会感到头疼。
这种方法可能是一个问题的原因是,您可能希望编写如下代码行:
let result = JSONDecoder().decode(networkType.returnType(), from: data)
这将中断,因为Decodable.Type
本身不是可解码的类型。(您解码 Int,但无法解码Int 的类型。说它确实有效。result
会是什么类型?你能用它做什么?你唯一知道的是它是可解码的(而且你已经解码了它(。
你可能想要更像Vasu Chand的实现,或者我的博客系列中讨论的类似方法。
您可以将转义闭包用于 API 调用的返回结果。
假设您正在点击一个 get 请求。一个简单的工作示例,用于传递获取请求 API 的可编码模型。
class func GETRequest<ResponseType :Decodable>(url : URL,responseType : ResponseType.Type ,completion: @escaping (ResponseType? ,Error? ) -> Void){
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else{
completion(nil,error)
return
}
let decoder = JSONDecoder()
do{
let responseData = try decoder.decode(ResponseType.self, from: data)
completion(responseData, nil)
}
catch let error{
completion(nil, error)
}
}
task.resume()
}
如何调用此网络函数。
Network.GETRequest(url: url, responseType: Model.self) { (model, error) in
completion(model,error)
}
模型类包含
struct Model : Codable{
}
您可以将任何get
请求的任何响应模型传递给网络类。
同样,您可以为post请求构建api网络,其中请求正文只是可编码的模型。
抱歉,您不能
根据需要在此处提供第一个参数JSONDecoder().decode(AdecodableType.self,from:data)
需要在编写代码时正确推断,以便它不能是符合Decodable
的类型集合中的任何 1