【问题标题】:How to generate and handle errors in Swift如何在 Swift 中生成和处理错误
【发布时间】:2017-04-04 12:45:30
【问题描述】:

我正在开发一个用户需要登录的应用程序。 Web 应用程序使用一个令牌,用户可以通过使用他们的用户名和密码调用 Web 服务来获得该令牌。我现在的问题是处理可能发生的错误的最佳方法是什么。我现在拥有的:

LoginViewController.swift

self.api.token(forUsername: "a", password: "b") { (result) in
    switch (result) {
    case .failure(let error):
        print("something when wrong \(error)")
    case .success(let token):
        print("token \(token)")
}

LoginAPIClient(self.api)使用https://github.com/3lvis/Networking

class LoginAPIClient {

enum ResponseError: Error {
    case unexpectedDataError
    case unknownError
}

enum Result {
    case success(String)
    case failure(Error)
}

lazy var networking: Networking = {
    let networking = Networking(baseURL: APIClient.serverURL())
    return networking
}()

func token(forUsername username: String, password: String, completion: @escaping (Result) -> Void) {
    let parameters = ["username" : username, "password" : password]
    networking.post("/api/login", parameters: parameters) { (result) in
        switch result {
        case .failure(let response):
            return completion(.failure(response.error))
        case .success(let response):
            if var token = response.headers["Authorization"] as? String {
                token = token.replacingOccurrences(of: "Bearer ", with: "")
                return completion(.success(token))
            }
            return completion(.failure(ResponseError.unknownError))
        }
    }
}

}

例如,我正在创建自己的错误return completion(.failure(ResponseError.unknownError)),以防服务器以成功的状态代码 (200) 进行响应,但响应中缺少 Authorization 标头。

这可行,唯一的问题是,现在当我在 ViewController 中处理错误时,我不知道它失败的确切原因。例如,从 Networking 库中,我得到一个错误代码(400 或 401 等),但它丢失了,因为它首先是一个 NSError。我可以使用 NSError 但不知何故这感觉不对。谁能指出我正确的方向?

我想到的解决方案之一是添加一个额外的枚举,然后执行以下操作:

enum Result {
    case success(String)
    case networkFailure(FailureJSONResponse)
    case failure(Error)
}

self.api.token(forUsername: "a", password: "b") { (result) in
switch (result) {
case .failure(let error):
    print("something when wrong \(error)")
case .networkFailure(let response):
    print("something when wrong \(error)")
case .success(let token):
    print("token \(token)")

}

但我宁愿在切换中只有 1 次成功和 1 次失败。

【问题讨论】:

    标签: ios swift networking error-handling


    【解决方案1】:

    每个应用程序通常都有自己的“错误”,所以在你的情况下你可以定义

    public enum AppError: Swift.Error, CustomStringConvertible {
        case networkError(code: Int)
        case anotherError(message: String?)
        case underlying(Swift.Error)
    
        public var description: String {
            switch self {
                case .networkError(let code):
                    return "Network error with code \(code)"
                default://I'm not gonna cover all cases, but you should :)
                    return "Error"
            }
        }
    }
    

    那么你可以使用你的方法

    enum Result {
        case success(String)
        case failure(AppError)
    }
    

    【讨论】:

    • 谢谢,这看起来是一种实现错误处理的干净方法!
    【解决方案2】:

    您可以将第二个参数添加到completion 块:

    func token(forUsername username: String, password: String, completion: @escaping (Result, error: ResponseError?) -> Void)

    【讨论】:

      猜你喜欢
      • 2015-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-03
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多