我想使静态FUNC时可能会返回类似这样定义的结构:
struct Category: Codable {
public let data: Array<CateItem>
public let status: Int
public let msg: String
}
我有写一个静态的FUNC这样的:
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
将无法正常工作。
如何解决这一问题?
你想传递结构,而不是协议的类型。
首先,为您的方法,说T
必须符合Decodable
(因为你需要它只是用于解码,你不需要符合Encodable
)泛型约束
然后说,参数的类型应该T.Type
的 - 这允许编译器推断T
的类型,你能避免使用此参数,请在答案的结尾
static func Get<T: Decodable>(codePoint: String, responseType: T.Type) { ... }
...所以T
将是你会传递给方法的类型。
那么对于JSONDecoder
的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) { ... }
HttpRequests.get(codePoint: "getCategoryList") { (category: Category?) -> Void in ... }