官术网_书友最值得收藏!

Sending requests with Encodable

The counterpart to Decodable is Encodable; an object that conforms to both Encodable and Decodable is Codable. Now that you have seen how to download data from a server and parse it into a pure Swift object, you'll probably want to send data to the server from pure Swift objects:

func post<T, U>(url: URL, body: U, callback: @escaping (T?, Error?) -> Void) throws 
-> URLSessionTask where T: Decodable, U: Encodable {
var request = URLRequest(url: url)
request.httpBody = try JSONEncoder().encode(body)
request.httpMethod = "POST"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
// Exact same code as in the get<T> callback, extracted
handleResponse(data: data,
response: response,
error: error,
callback: callback)
}
task.resume()
return task
}

As you can see, we have now minimally changed the implementation of the original get<T>. That begs for a higher level of abstraction on both URLSession and URLRequest:

  1. We can make the URLRequest class aware of the body parsing logic, as follows:
extension URLRequest {
enum HTTPMethod: String {
case GET
case POST
case PUT
case DELETE
}

init<T>(url: URL, method: HTTPMethod, body: T?) throws where T: Encodable {
self.init(url: url)
httpMethod = method.rawValue
if let body = body {
httpBody = try JSONEncoder().encode(body)
}
}
}
  1. Let's update URLSession with the response parsing logic, over the dataTask call:
extension URLSession {
func dataTask<T>(with request: URLRequest,
callback: @escaping (T?, Error?) -> Void)
throws -> URLSessionTask where T: Decodable {
return URLSession.shared.dataTask(with: request) { data, response, error in
handleResponse(data: data,
response: response,
error: error,
callback: callback)
}
}
}
  1. With those abstractions done, we can finally use our enhanced URLSession all over our program. Let's start with the new URLRequest:
let request = try! URLRequest(url: URL(string: "http://example.com")!,
method: .POST,
body: MyBody())
  1. We can then get URLSessionDataTask from URLSession:
let task = try? URLSession.shared.dataTask(with: request) { (result: MyResult?, error) in
// Handle result / error
}
task?.resume()

You now have the basic building blocks required to build a type-safe and powerful network client. You'll be able to reuse these patterns across your programs, as they are very generic.

主站蜘蛛池模板: 阜南县| 大同县| 彰化县| 长岭县| 同心县| 广州市| 玉山县| 明水县| 古蔺县| 淮南市| 邯郸县| 浙江省| 金溪县| 康保县| 麦盖提县| 华容县| 镶黄旗| 九寨沟县| 延吉市| 五常市| 沂南县| 宜君县| 图们市| 怀集县| 昌都县| 裕民县| 漳州市| 河源市| 剑河县| 满洲里市| 郎溪县| 郯城县| 油尖旺区| 林芝县| 江津市| 阿拉尔市| 新营市| 葫芦岛市| 凌云县| 福鼎市| 辉南县|