Swift 5 引入了新的 Result 类型来处理异步函数的结果。我想知道如何将这种新的结果类型用于 URLSession。
我有以下代码。
func getCategorByAPI()
{
//Base Url is from an static variable
let url = URL(string: URLManager.aPIBaseURL+"category")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
//print("error=\(error)")
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary
print(json)
}catch
{
print(error)
}
}
task.resume()
}
Run Code Online (Sandbox Code Playgroud)
如何使用 swift 5 Result 类型重写此函数?
小智 7
您想创建一个enum指定结果中可能出现的情况(例如成功或失败)。然后向getCategorByAPI()类型为 的方法添加完成Result<Data, Error>。从那里,在 url 会话中,您将调用您的完成处理程序,传入dataon.success或erroron .failure。
您还可以做一些很酷的事情,例如覆盖 Result 的get()方法并扩展Result以解码您的数据:D
一探究竟:
enum Result<Success, Error: Swift.Error> {
case success(Success)
case failure(Error)
}
// override the Result.get() method
extension Result {
func get() throws -> Success {
switch self {
case .success(let value):
return value
case .failure(let error):
throw error
}
}
}
// use generics - this is where you can decode your data
extension Result where Success == Data {
func decoded<T: Decodable>(using decoder: JSONDecoder = .init()) throws -> T {
let data = try get()
return try decoder.decode(T.self, from: data)
}
}
func getCategorByAPI(completion: (Result<Data, Error>) -> Void)
{
// You might want to stick this into another method
let url = URL(string: URLManager.aPIBaseURL+"category")!
var request = URLRequest(url: url)
request.httpMethod = "GET"
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
completion(.failure(error))
return
}
if !(200...299).contains(httpResponse.statusCode) && !(httpResponse.statusCode == 304) {
let httpError = // ... convert httpResponse.statusCode into a more readable error
completion(.failure(httpError))
}
if let data = data {
completion(.success(data))
}
}.resume()
}
Run Code Online (Sandbox Code Playgroud)
我还没有测试上述内容,但在当前项目中实现了类似的内容。以下是我阅读的一些关于如何实施的文章:
https : //www.hackingwithswift.com/articles/161/how-to-use-result-in-swift
https://medium.com/@pavlepesic/how -to-use-swift-5-result-with-codable-protocol-824c9a951af9
我在 URLSession 上编写了一个扩展,它抽象出了错误处理和解码的样板代码。
extension URLSession {
/// A type safe URL loader that calls completion handler with Result type
func jsonDecodableTask<T: Decodable>(with url: URLRequest, decoder: JSONDecoder = JSONDecoder(), completion: @escaping (Result<T, Error>) -> Void) -> URLSessionDataTask {
self.dataTask(with: url) { (data, _, error) in
guard error == nil else {
completion(.failure(error!))
return
}
guard let data = data else {
completion(.failure(URLError.noData))
return
}
do {
let decoded = try decoder.decode(T.self, from: data)
completion(.success(decoded))
} catch {
completion(.failure(error))
}
}
}
func jsonDecodableTask<T: Decodable>(with url: URL, decoder: JSONDecoder = JSONDecoder(), completion: @escaping (Result<T, Error>) -> Void) -> URLSessionDataTask {
self.jsonDecodableTask(with: URLRequest(url: url), decoder: decoder, completion: completion)
}
}
Run Code Online (Sandbox Code Playgroud)
struct Person: Codable {
let name: String
let age: Int
}
let url = URL(string: "https://abcd.com")!
URLSession.shared.jsonDecodableTask(with: url) { (result: Result<Person, Error>) in
switch result {
case .success(let person):
print("Person \(person.name)")
case .failure(let error):
print(error)
}
}.resume()
Run Code Online (Sandbox Code Playgroud)
你也可以JSONDecoder像这样传递你自己的
let urlRequest = URLRequest(url: url)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
URLSession.shared.jsonDecodableTask(with: urlRequest, decoder: decoder) { (result: Result<Person, Error>) in
// Same as above
}.resume()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5110 次 |
| 最近记录: |