[swift]Alert内の処理に応じて再びAlertを表示したい（AlertActionを引数にする）

タイトル長くなりがち。

###やりたい事

アカウント設定画面でログアウトボタンを押した時に、

- 「ログアウトしますか？」というダイアログに「OK」/「キャンセル」の選択肢を用意。

- 「OK」を押すと、APIでログアウト処理が行われる。
→成功すると、「ログアウトしました」というダイアログが表示され、画面が遷移する。
→失敗すると、「ログアウトに失敗しました」というアラートが表示される。
- 「キャンセル」を押すと、最初のダイアログが消える。

っていう処理を行いたい:hugging:

###とりあえず作ってみた

今回は、

- ちゃんと読んでほしいアラートは手動で閉じる。
- お知らせ程度のダイアログは勝手に消える。

みたいな感じでメソッドを使い分けています。

```AccountViewController.swift
import UIKit
final class AccountViewController: UIViewController {
    @IBAction private func tappedLogoutButton(_ sender: UIButton) {
        let dialog: UIAlertController = UIAlertController(title: "ログアウト",
                                                          message: "ログアウトしますか？",
                                                          preferredStyle: .alert)
        dialog.addAction(UIAlertAction(title: "OK", style: .default) { _ in
            // 本来はAPI通信の結果をresultに入れています。（今回は割愛）
            let result:Bool = true
            switch result {
            case true:
                AlertUtil.showAlert(title: "Success", message: "ログアウトに成功しました。",viewController: self)
                // 以下に画面遷移処理を追加。（今回は割愛）
            case false:
                AlertUtil.showAlert(title: "ログアウト失敗", message: "ログアウトに失敗しました。", viewController: self)
            }
            dialog.addAction(UIAlertAction(title: "閉じる", style: .cancel))
            self.present(dialog, animated: true)
        })
        
    }
    
}
```

```AlertUtil.swift
struct AlertUtil {
    static func showDialog(title: String, message: String, viewController: UIViewController) {
        let dialog = UIAlertController(title: title,
                                       message: message,
                                       preferredStyle: .alert)
        viewController.present(dialog, animated: true) {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) {
                dialog.dismiss(animated: true, completion: nil)
            }
        }
    }

    static func showAlert(title: String, message: String, viewController: UIViewController) {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: title,
                                          message: message,
                                          preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "キャンセル",
                                          style: .default))
            viewController.present(alert, animated: true)
        }
    }
}
```

上のコードだと、

> :raising_hand:
アラート関連の処理はAlertUtilにまとめちゃお！
でも、API通信の結果によってaddActionの処理を分けたいから・・・
最初のダイアログだけViewControllerで作っちゃお！

って感じ。

でも、他の部分ではアラート表示をAlertUtilで行なっているから、

なるべく統一していきたいな・・・

という事で:open_hands:

### alertActionを引数にとる

スッキリ統一感のあるコードにするために、alertActionを引数にとる形に変更してみます。

```AccountViewController.swift
import UIKit
final class AccountViewController: UIViewController {
    @IBAction private func tappedLogoutButton(_ sender: UIButton) {
        let alertAction: UIAlertAction = UIAlertAction(title: "OK", style: .default) { _ in
            // 本来はAPI通信の結果をresultに入れています。（今回は割愛）
            let result:Bool = true
            switch result {
            case true:
                AlertUtil.showAlert(title: "Success", message: "ログアウトに成功しました。",viewController: self)
                // 以下に画面遷移処理を追加。（今回は割愛）
            case false:
                AlertUtil.showAlert(title: "ログアウト失敗", message: "ログアウトに失敗しました。", viewController: self)
            }
        }
        AlertUtil.showChoiceDialog(title: "ログアウト", message: "ログアウトしますか？", viewController: self, alertAction: alertAction)
    }
}
```



```AlertUtil.swift
struct AlertUtil {
    static func showDialog(title: String, message: String, viewController: UIViewController) {
        let dialog = UIAlertController(title: title,
                                       message: message,
                                       preferredStyle: .alert)
        viewController.present(dialog, animated: true) {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) {
                dialog.dismiss(animated: true, completion: nil)
            }
        }
    }

    static func showAlert(title: String, message: String, viewController: UIViewController) {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: title,
                                          message: message,
                                          preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "キャンセル",
                                          style: .default))
            viewController.present(alert, animated: true)
        }
    }
    
    // このメソッドを追加
    static func showChoiceDialog(title: String, message: String, viewController: UIViewController, alertAction: UIAlertAction) {
        let dialog: UIAlertController = UIAlertController(title: title,
                                                          message: message,
                                                          preferredStyle: .alert)
        dialog.addAction(UIAlertAction(title: "キャンセル", style: .default))
        dialog.addAction(alertAction)
        viewController.present(dialog, animated: true)
    }
}
```

こうする事で、

showAlert系のメソッドは全てAleretUtilで作成する事に統一し、

AccountViewController内の記述もスッキリしました:ok_woman::sparkles: