我想制作一个静态函数,它可以返回如下定义的struct:
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)
但是这里CCD_ 1将不起作用。
如何解决此问题?
您想要传递的是结构的类型,而不是协议。
首先,为您的方法制定通用约束,规定T
必须符合Decodable
(因为您只需要它进行解码,所以不需要符合Encodable
)
然后说参数的类型应该是T.Type
-这允许编译器推断类型的T
,您可以避免使用此参数,请参阅答案的末尾
static func Get<T: Decodable>(codePoint: String, responseType: T.Type) { ... }
所以T
将是您要传递给方法的类型。
然后对于JSONDecoder
的decode
方法使用responseType
0 类型
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) { ... }
HttpRequests.get(codePoint: "getCategoryList") { (category: Category?) -> Void in ... }