我想制作一个静态函数,该函数可以返回如下所示的结构:
struct Category: Codable {
public let data: Array<CateItem>
public let status: Int
public let msg: String
}
我已经写了一个像这样的静态函数:
static func Get(codePoint: String, responseType: Codable){
let urlString = UrlUtils.GetUrl(codePoint: codePoint)
let url = URL(string: urlString)
let task = URLSession.shared.dataTask(with: url!){
(data,response,error) in
if error != nil{
print(error!)
}else{
if let data = data{
JSONDecoder().decode(responseType, from: data)
}
}
}
task.resume()
}
并调用如下方法:
HttpRequests.Get(codePoint: "getCategoryList", responseType: Category)
但是这里responseType
无效。
该如何解决?
答案 0 :(得分:4)
您要传递结构类型,而不是协议。
首先,对方法进行一般约束,即说T
必须符合Decodable
(由于仅用于解码就需要它,因此不需要符合Encodable
)
然后说参数应该为T.Type
类型-这允许编译器推断类型为T
,您可以避免使用此参数,请参见回答
static func Get<T: Decodable>(codePoint: String, responseType: T.Type) { ... }
...因此T
将是您将传递给方法的类型。
然后,JSONDecoder
的{{1}}方法使用的类型为decode
T
,然后当您要调用方法时,像在解码中一样传递结构的类型
JSONDecoder().decode(T.self, from: data)
还要注意,您的调用是异步的,因此要返回数据,您需要将补全处理程序定义为方法的参数
HttpRequests.Get(codePoint: "getCategoryList", responseType: Category.self)
请注意,方法名称应以小写大写字母开头
completion: @escaping (T?) -> Void
static func get<T: Decodable>(codePoint: String, responseType: T.Type, completion: @escaping (T?) -> Void) {
let urlString = UrlUtils.GetUrl(codePoint: codePoint)
let url = URL(string: urlString)
URLSession.shared.dataTask(with: url!) { data, response, error in
guard let data = data else {
print(error!)
return completion(nil)
}
do {
let decoded = try JSONDecoder().decode(T.self, from: data)
completion(decoded)
} catch {
print(error)
completion(nil)
}
}.resume()
}
您还可以避免使用HttpRequests.get(codePoint: "getCategoryList", responseType: Category.self) { response in
if let category = response {
...
}
}
参数,因为responseType
的类型可以从完成闭包的参数类型中推断出来
T
static func get<T: Codable>(codePoint: String, completion: @escaping (T?) -> Void) { ... }