如何使 returns 成为 Swift 中的可解码类型的函数?
How to make a function that returns a decodable type in Swift?
所以我有这个枚举,用于我在我的应用程序中使用的少数 url 请求:
enum Netwrok {
case popular
case topRated
case latest
// ...
static let baseUrl = "http://..."
func path() -> String {
switch self {
case .popular: return "/popular"
// ...
}
}
}
我想添加一个函数,returns 网络堆栈解码数据所用的模型的可解码类型。
所以我认为类似的东西可以完成这项工作:
func returnType<T>() -> T.Type where T : Decodable {
switch self {
case .popular:
return Popular.self
// ...
}
}
但我无法让它工作,它说:
Cannot convert return expression of type 'Popular.Type' to return type 'T.Type'
要我强制施法 T.Type
。
我如何创建一个 returns 可解码的函数,以便可以处理该类型但 JSONDecoder 的解码函数?
谢谢。
很抱歉您不能根据您的需要在这里提供第一个参数
JSONDecoder().decode(AdecodableType.self,from:data)
需要在编写代码时正确推断,因此它不能是符合 Decodable
的类型集合中的任何 1
您可以使用 escaping 闭包 作为 API 调用的返回结果。
假设您正在点击获取请求。为 get 请求传递 Codable 模型的简单工作示例 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)
}
型号class包含
struct Model : Codable{
}
您可以将任何 get
请求的任何响应模型传递给网络 class。
同样,您可以为 post 请求构建 api 网络,其中请求主体只是 Codable 模型。
您的要求很简单,但可能不是您想要的。您要求做的是 return 类型。没有什么通用的。
func returnType<T>() -> T.Type where T : Decodable {
此语法定义了一个类型参数 T
,它由 调用者 传递。它不是由您的函数定义的。这意味着调用者可以传递 any 可解码的类型,而您的函数将 return 它。例如,调用者可以将 T
设置为 Int(因为它是 Decodable),您将 return Int.Type
。这很容易实现 (return T.self
),但不是你的意思。
你的意思是函数 return 是函数知道的 Decodable 类型,但调用者不知道:
func returnType() -> Decodable.Type { ... }
这会很好地工作,并且完全按照您的要求进行,但它表明您可能未正确构建此网络堆栈,以后会很头疼。
这种方法可能会出现问题的原因是您可能想编写这样一行代码:
let result = JSONDecoder().decode(networkType.returnType(), from: data)
这会中断,因为 Decodable.Type
本身 不是 可解码类型。 (你解码了 Int,但是不能解码 Int 的 type。)说它确实有效。 result
是什么类型?你能用它做什么?你唯一知道的是它是可解码的(而且你已经解码了它)。
您可能想要更像 Vasu Chand 的实现,或者 the similar approach discussed in my blog series。
所以我有这个枚举,用于我在我的应用程序中使用的少数 url 请求:
enum Netwrok {
case popular
case topRated
case latest
// ...
static let baseUrl = "http://..."
func path() -> String {
switch self {
case .popular: return "/popular"
// ...
}
}
}
我想添加一个函数,returns 网络堆栈解码数据所用的模型的可解码类型。
所以我认为类似的东西可以完成这项工作:
func returnType<T>() -> T.Type where T : Decodable {
switch self {
case .popular:
return Popular.self
// ...
}
}
但我无法让它工作,它说:
Cannot convert return expression of type 'Popular.Type' to return type 'T.Type'
要我强制施法 T.Type
。
我如何创建一个 returns 可解码的函数,以便可以处理该类型但 JSONDecoder 的解码函数?
谢谢。
很抱歉您不能根据您的需要在这里提供第一个参数
JSONDecoder().decode(AdecodableType.self,from:data)
需要在编写代码时正确推断,因此它不能是符合 Decodable
您可以使用 escaping 闭包 作为 API 调用的返回结果。
假设您正在点击获取请求。为 get 请求传递 Codable 模型的简单工作示例 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)
}
型号class包含
struct Model : Codable{
}
您可以将任何 get
请求的任何响应模型传递给网络 class。
同样,您可以为 post 请求构建 api 网络,其中请求主体只是 Codable 模型。
您的要求很简单,但可能不是您想要的。您要求做的是 return 类型。没有什么通用的。
func returnType<T>() -> T.Type where T : Decodable {
此语法定义了一个类型参数 T
,它由 调用者 传递。它不是由您的函数定义的。这意味着调用者可以传递 any 可解码的类型,而您的函数将 return 它。例如,调用者可以将 T
设置为 Int(因为它是 Decodable),您将 return Int.Type
。这很容易实现 (return T.self
),但不是你的意思。
你的意思是函数 return 是函数知道的 Decodable 类型,但调用者不知道:
func returnType() -> Decodable.Type { ... }
这会很好地工作,并且完全按照您的要求进行,但它表明您可能未正确构建此网络堆栈,以后会很头疼。
这种方法可能会出现问题的原因是您可能想编写这样一行代码:
let result = JSONDecoder().decode(networkType.returnType(), from: data)
这会中断,因为 Decodable.Type
本身 不是 可解码类型。 (你解码了 Int,但是不能解码 Int 的 type。)说它确实有效。 result
是什么类型?你能用它做什么?你唯一知道的是它是可解码的(而且你已经解码了它)。
您可能想要更像 Vasu Chand 的实现,或者 the similar approach discussed in my blog series。