はじめに
エラーハンドリングは、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を御覧ください。
以上です。