RxSwiftでPresenterで発生したエラーをViewで表示させる


RxSwiftでエラーをキャッチした後に、
PresenterからViewへエラーを流すパターン

LoginPresenterでログイン処理をした後、LoginViewControllerにErrorを流す。
SignalはDriverとだいたい同じものですが、Driverと違いsubscribeされるときにreplayしません。
ログイン処理などAPIを叩く処理ではreplayを意識する必要がないのでSignalにしています。

DriverとSignalについては以下の解説がわかりやすい

RxCocoa 4 の Signal と Relay のまとめ
https://engineering.mercari.com/blog/entry/2017-12-04-103247/

LoginPresenter

protocol LoginPresenter {
    var showAPIErrorPopupRelay: Signal<Error> { get }
}

final class LoginPresenterImpl: LoginPresenter {
    private let _showAPIErrorPopupRelay = PublishRelay<Error>()
    var showAPIErrorPopupRelay: Signal<Error> {
        return _showAPIErrorPopupRelay.asSignal()
    }
}

LoginViewController

error.localizedDescriptionで、エラーの内容を参照して表示させる。

class LoginViewController: UIViewController {
        presenter.showAPIErrorPopupRelay
            .emit(onNext: { [weak self] error in
                self?.showErrorAlert(message: error.localizedDescription)
            })
            .disposed(by: bag)
}

UIViewControllerのExtension

extension UIViewController {
    func showErrorAlert(message: String, completion: (() -> Void)? = nil) {
        let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
        let action = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(action)
        present(alert, animated: true)
    }
}