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

  • Hands-On Design Patterns with Swift
  • Florent Vilmart Giordano Scalzo Sergio De Simone
  • 351字
  • 2021-07-02 14:45:13

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.

主站蜘蛛池模板: 轮台县| 沛县| 和平县| 南丹县| 偃师市| 广南县| 平昌县| 呼和浩特市| 依兰县| 丰台区| 沙坪坝区| 上杭县| 温泉县| 永新县| 伊金霍洛旗| 三原县| 湛江市| 溆浦县| 久治县| 禹城市| 浦城县| 安化县| 买车| 金寨县| 兴仁县| 海兴县| 集安市| 台前县| 比如县| 迁安市| 房山区| 甘谷县| 北京市| 顺昌县| 靖安县| 永和县| 楚雄市| 新蔡县| 宁乡县| 上蔡县| 连云港市|