[Swift]Firebaseでのログイン機能

作成しているアプリでFirebaseを用いてログイン機能を実装しているので
一部を簡潔に、備忘録として残しておきます。

#①エラー処理
Result型でエラーを返すので自前で用意します。

``` ruby:AuthError.swift
import Foundation

enum AuthError: Error {
    case userCreate
    case userLogin
    case createToDo
    case addToDo
    case getToDo
    case getUser
    case getUserName
    case updateToDo
    case doneToDo
    case deleteToDo
    case reLogin
    case deleteData

    var title: String {
        return "通信エラー"
    }

    var message: String {
        switch self {
        case .userCreate:
            return "ユーザの作成に失敗しました"
        case.userLogin:
            return "ログインに失敗しました"
        case.createToDo:
            return "ToDoの作成に失敗しました"
        case.addToDo:
            return "ToDoの追加に失敗しました"
        case.getToDo:
            return "ToDoの取得に失敗しました"
        case.getUser:
            return "ユーザーの取得に失敗しました"
        case.getUserName:
            return "ユーザーネームの取得に失敗しました"
        case.updateToDo:
            return "ToDoの更新に失敗しました"
        case.doneToDo:
            return "ToDoの切り替えに失敗しました"
        case.deleteToDo:
            return "ToDoの削除に失敗しました"
        case.reLogin:
            return "再ログインに失敗しました"
        case.deleteData:
            return "データを削除できませんでした"
        default:
            return "エラーが発生しました"
        }
    }
}
```

#②Model
下記のようなモデルを用意します。

```ruby:UserModel.swift
import Foundation

struct UserModel {
    var emailStr: String?
    var passwordStr: String?
    var nameStr: String?
}
```

#③ユーザー作成とログイン

ユーザー作成とログインのメソッドです。

```ruby:UserAuth.swift
final class UserAuth {

    static func fierstCreate(model: UserModel, completion: ((Result<Void, AuthError>) -> Void)?) {

        AuthFirebase.auth.createUser(withEmail: model.emailStr!, password: model.passwordStr!, completion: { (result, error) in
            if let _error = error {
                completion?(.failure(AuthError.userCreate))
                return
            }
            guard let user = result?.user else {
                completion?(.failure(AuthError.userCreate))
                return
            }
            print("ユーザー作成完了 uid:" + user.uid)
            // ②FirestoreのUsersコレクションにdocumentID = ログインしたuidでデータを作成する
            Database.db.collection("users").document(user.uid).setData([
                "name": model.nameStr!
            ], completion: { error in
                if let _error = error {
                    print("コレクションに保存できません")
                    completion?(.failure(AuthError.userCreate))
                    return
                }
                print("ユーザー作成完了 name:" + model.nameStr!)
                completion?(.success(()))
            })
        })

    }

    static func logined(model: UserModel, completion: ((Result<Void, AuthError>) -> Void)?) {
        // ①FirebaseAuthにemailとpasswordでログインを行う
        AuthFirebase.auth.signIn(withEmail: model.emailStr!, password: model.passwordStr!, completion: { (result, error) in
            if let _error = error {
                print("ログイン失敗 ")
                completion?(.failure(AuthError.userLogin))
            }
            guard let user = result?.user else {
                print("ログイン失敗 ")
                completion?(.failure(AuthError.userLogin))
                return
            }
            print("ログイン完了 uid:" + user.uid)
            completion?(.success(()))
        })
    }
```

#④コントローラー側の処理
ViewController側でメソッドを呼び出します。
エラー処理はこちらで。

```ruby:LoginViewController.swift
 @IBAction private func tapLogin(_ sender: Any) {
        guard  let loginMailText = loginMailTextField.text,
               let loginPassText = loginPassTextField.text else {
            return
        }

        let userInfo = UserModel.init(emailStr: loginMailText, passwordStr: loginPassText)

        UserAuth.logined(model: userInfo) { result in
            switch result {
            case.failure(let error):
                let dialog = UIAlertController(title: error.title, message: error.message, preferredStyle: .alert)
                dialog.addAction(UIAlertAction(title: Constant.ok, style: .default, handler: nil))
                self.present(dialog, animated: true, completion: nil)
            case.success():
                #//メインの画面に遷移するコード
            }
        }
       
    }
```

```ruby:SignInViewController.swift
@IBAction private func tapRegister(_ sender: Any) {
        guard let emailText = emailTextField.text,
              let userText = userTextField.text,
              let passText = passTextField.text else {
            return
        }

        let userInfo = UserModel.init(emailStr: emailText, passwordStr: passText, nameStr: userText)

        UserAuth.fierstCreate(model: userInfo) { result in
            switch result {
            case.failure(let error):
                let dialog = UIAlertController(title: error.title, message: error.message, preferredStyle: .alert)
                dialog.addAction(UIAlertAction(title: Constant.ok, style: .default, handler: nil))
                self.present(dialog, animated: true, completion: nil)
            case.success():
                 #//メインの画面に遷移するコード
            }

        }
    }
```