LoginSignup
9
7

More than 5 years have passed since last update.

[Swift] ViewControllerのエラーハンドリングをクリーンに保つ

Last updated at Posted at 2016-08-29

はじめに

エラーハンドリングは、catchによる分岐が増えると
ソースの可読性が落ちて読みづらいですよね。

そこで、CustomStringConvertibleプロトコルを利用して、
ちょっとだけすっきりさせる方法をご紹介します。

今回ご説明する例

ログイン画面で、
バリデーションチェック(空文字禁止)する場合を例にご説明します。

よくある書き方

(1) 独自のエラーを定義する

LoginError.swift
import Foundation

enum LoginError: ErrorType {
    case emptyUsername
    case emptyPassword
}

(2) ログインボタン押下時に、バリデーションチェックする

現状は必須入力のみですが、フォーマットチェックや文字数などチェックが増えると、
caseがどんどん増えていきます。

ViewController.swift
    func login() {

        do {
            let token = try loginUserWithUsername(nil, password: nil)
            print(token)

        } catch LoginError.emptyUsername {
            print("ユーザ名は必須入力です")
        } catch LoginError.emptyPassword {
            print("パスワードは必須入力です")
        } catch {
            print(error)
        }
    }

    func loginUserWithUsername(username: String?, password: String?) throws -> String{
        guard let username = username where !username.isEmpty else {
            throw LoginError.emptyUsername
        }

        guard let password = password where !password.isEmpty  else {
            throw LoginError.emptyPassword
        }

        //Do Something
        return "tokenIDを返します"
    }

ご提案する方法

(1) 独自のエラーを定義する

ここは同じです。

LoginError.swift
import Foundation

enum LoginError: ErrorType {
    case emptyUsername
    case emptyPassword
}

(2) CustomStringConvertibleを利用し、descriptionメソッドを実装する

バリデーションチェックのパターン分追記する。

LoginError.swift
extension LoginError : CustomStringConvertible {
    var description: String {
        switch self {
        case .emptyUsername:
            return "ユーザ名は必須入力です"

        case .emptyPassword:
            return "パスワードは必須入力です"
        }
    }
}

(3) ログインボタン押下時に、バリデーションチェックする

現状は、必須入力だけですが、書式や文字数など増えても、
ViewControllerへの影響はありません。

ViewController.swift
    func login() {

        do {
            let token = try loginUserWithUsername(nil, password: nil)
            print(token)

        }  catch let error as LoginError {
            print(error.description)
        } catch {
            print(error)
        }
    }

    func loginUserWithUsername(username: String?, password: String?) throws -> String{
        guard let username = username where !username.isEmpty else {
            throw LoginError.emptyUsername
        }

        guard let password = password where !password.isEmpty  else {
            throw LoginError.emptyPassword
        }

        //Do Something
        return "tokenIDを返します"
    }

まとめ

catchが増えると、ソースコードがカオスになりやすいですね。
エラーメッセージだけでも、切り出すとすっきりしたような気がします。

ちなみに、Swift3ではエラーハンドリングに変更があるようです。

Swift3の場合
import Foundation

enum LoginError : Error {
    case emptyUsername
    case emptyPassword
}

Swift3版のサンプルは、Githubを御覧ください。

以上です。

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7