2017-04-04 8 views
1

私はユーザーがログインする必要があるアプリで作業しています。 Webアプリケーションはトークンを使用し、ユーザーはユーザー名とパスワードを使用してWebサービスを呼び出すことができます。今私の質問は、発生する可能性のあるハンドルエラーを処理する最良の方法です。私は今持っているもの:使用Swiftでエラーを生成して処理する方法

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)) 
     } 
    } 
} 

}ここで私は自分のエラーを作成しています例えば

サーバーが正常なステータスコード(200)で応答するが、何らかの理由でAuthorizationヘッダーが応答にない場合はreturn completion(.failure(ResponseError.unknownError))となります。

これがうまくいけば、唯一の問題はViewControllerでエラーを処理するときに、なぜ失敗するのか正確な理由がわからないことです。たとえば、Networkingライブラリからは、エラーコード(400または401など)が返されますが、最初はNSErrorだったため、これは失われます。私はNSErrorを使うことができましたが、どういうわけかこれは正しいとは感じません。誰かが私を正しい方向に向けることができますか?

私が考える解決策の1つは、余分な列挙型を追加することでしたし、このような何か:

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つの失敗を持っています。

答えて

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) 
} 
+0

ありがとう、これはきれいなwのように見えますエラー処理を実装するにはどうしたらいいですか? – Bart

0

あなたはcompletionブロックに2つ目のパラメータを追加することができます

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

関連する問題