问题描述
Swift 5 引入了新的 Result 类型来处理异步函数的结果.我想知道如何将这种新的结果类型用于 URLSession.
Swift 5 introduces new Result type to handle the result of an asynchronous function. I want to know the way to use this new result type for 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()
}
如何使用 swift 5 Result 类型重写此函数?
How can i rewrite this function using swift 5 Result type?
推荐答案
您想要创建一个 enum
来指定结果中的可能情况(例如成功或失败).然后向 getCategorByAPI()
方法添加一个类型为 Result
的完成.从那里,在 url 会话中,您将调用完成处理程序,传入 .success
上的 data
或 上的
.error
.失败
You want to create an enum
that specifies the possible cases in your result (e.g. success or failure). Then you add a completion to your getCategorByAPI()
method that is of type Result<Data, Error>
. From there, inside url session, you will call your completion handler passing in either the data
on .success
or the error
on .failure
.
你也可以做一些很酷的事情,比如覆盖 Result 的 get()
方法并扩展 Result
来解码你的数据 :D
You can also do cool things like override Result's get()
method and extend Result
to decode your data :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()
}
我还没有测试过上述内容,但在当前项目中实现了类似的内容.以下是我阅读的一些文章,以了解如何实施:
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
I haven't tested the above but have something like this implemented in a current project. Here are some articles I read to learn about how to implement:
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
这篇关于如何使用 swift 5 URLSession 中引入的新 Result 类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!