我正在尝试创建一个通用函数,以从Web服务下载json,当前此功能很好用,但是我不确定这是一个好方法还是最好的方法。
是否可以将其作为URLSession的一部分?, 可以将其用作类函数吗?, 还有没有更好的方法来处理错误?
enum HTTPMethod: String{
case GET
case POST
}
extension URLSession{
class func genericFetchData<T: Codable>(urlString: String, parameters:[String: Any]?, method: HTTPMethod = .GET, completion: @escaping(T?, NSError?) -> Void) {
guard var urlComponents = URLComponents(string: urlString) else {
let error = NSError(domain: urlString, code: 400, userInfo: ["Error " : "URL error."])
completion(nil, error)
return
}
if let items = create(parameters) {
urlComponents.queryItems = items
}
guard let url = urlComponents.url else {
let error = NSError(domain: "Parameters", code: 400, userInfo: ["Error " : "Unable to create url using parameter you inlcuded."])
completion(nil, error)
return
}
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
URLSession.shared.dataTask(with: request) { (data, res, error) in
guard let data = data else{
let error: NSError = error! as NSError
completion(nil, error)
return
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
if let obj = try? decoder.decode(T.self, from: data){
completion(obj, nil)
} else{
let error = NSError(domain: urlString, code: 500, userInfo: ["Error" : "The data couldn’t be read because it isn’t in the correct format."])
completion(nil, error)
}
}.resume()
}
private static func create(_ parameters: [String: Any]?) -> [URLQueryItem]? {
var queryItems = [URLQueryItem]()
guard let unwrappedParameters = parameters else {
return nil
}
for (key, value) in unwrappedParameters {
let strValue = String(describing: value)
queryItems.append(URLQueryItem(name: key, value: strValue))
}
return queryItems
}
}