Networking Layer in Swift , Completion Blocks and Errors
我正在用 Swift 实现一个网络层。这是功能之一。该功能按预期工作,但我想改进它。我正在使用 DispatchQueue 来确保来自网络客户端的回调始终在主线程上。这最终会在 3 个不同的地方重复 DispatchQueue.main.async。
此外,当我在执行请求时遇到一些错误时,我仍然会返回 nil 但作为成功。
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
func getAllStocks(url: String, completion: @escaping (Result<[Stock]?,NetworkError>) -> Void) {
guard let url = URL(string: url) else { URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { return let stocks = try? JSONDecoder().decode([Stock].self, from: data) } } |
我怎样才能最小化代码或者它可以吗?
- 尝试 CodyFire 库
Result 类型的目标是在成功时返回非可选类型,在失败时返回错误。
我建议在当前线程上调用 completion 并在调用方发送结果。
同时处理 DecodingError
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
func getAllStocks(url: String, completion: @escaping (Result<[Stock],Error>) -> Void) {
guard let url = URL(string: url) else { URLSession.shared.dataTask(with: url) { data, response, error in if let error = error { completion(.failure(error)); return } |
|
1
2 3 4 5 6 7 8 9 10 |
getAllStocks(url: someURL) { result in
DispatchQueue.main.async { switch result { case .success(let stocks): print(stocks) case .failure(let networkError as NetworkError): handleNetworkError(networkError) case .failure(let decodingError as DecodingError): handleDecodingError(decodingError) case .failure(let error): print(error) } } } |
- 好看多了!谢谢!
了解内置结构和标准类型。
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
func getAllStocks(url: String, completion: @escaping (Result<[Stock], Error>) -> Void) {
func completeOnMain(_ result: Result<[Stock], Error>) { // <– Nested function DispatchQueue.main.async { completion(result) } // <– Handle repeated work } guard let url = URL(string: url) else { URLSession.shared.dataTask(with: url) { data, response, error in let stocks = try JSONDecoder().decode([Stock].self, from: data) completeOnMain(.success(stocks)) |
- 嵌套函数用于重复调度到主线程的工作。
- 使用标准错误而不是定义自定义错误。
- do/catch 和 throws 用于一次处理所有错误。
我有最后一点:异步函数应该始终是异步的。 bad URL错误不应该直接调用completion(_:);使用 DispatchQueue.main.async 确保调用发生在以后的运行循环中。
来源:https://www.codenong.com/59845923/
