RxSwift(MVVM)でのインディケーター表示状態の管理
自分は普段こうやっています的な紹介と悩み
インディケーターの状態管理について、自分はいつも以下のような形で管理しています。
enum LoadingStatus { case none case loading case dismiss } class XViewModel { private let disposeBag = DisposeBag() let loadingStatus: BehaviorRelay<LoadingStatus> = BehaviorRelay(value: .none) let isSuccess: PublishRelay<Bool> = PublishRelay() func fetchData() { AnySession .subscribe(onNext: { [weak self] _ in guard let self = self else { return } self.loadingStatus.accept(.dismiss) }, onError: { [weak self] _ in self.loadingStatus.accept(.dismiss) }) .disposed(by: disposeBag) } } class XViewController: UIViewController { let viewModel = XViewModel() private let disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() setupObserver() viewModel.fetchData() } func setupObserver() { viewModel.loadingStatus .subscribe(onNext: { status in switch status { case .none: break case .loading: // インディケーターを出す処理 case .dismiss: // インディケーターを消す処理 } }) .disposed(by: disposeBag) } }
これ自体はHUDの表示非表示の状態管理が割と綺麗な形でできていると思います(個人的には)。 ただ、これだとエラーの時に数秒だけ表示させるエラー表示のインディケーター(HUD?)の管理が同時にできないので悩んでいます。 LoadingStatusを
enum LoadingStatus { case none case loading case error(message: String) case dismiss }
みたいな形にすることも検討したのですが、運用する時に
// ViewModel func fetchData() { AnySession .subscribe(onNext: { [weak self] _ in guard let self = self else { return } self.loadingStatus.accept(.dismiss) }, onError: { [weak self] _ in self.loadingStatus.accept(.error(message: "エラーが発生しました")) }) .disposed(by: disposeBag) } // ViewController func setupObserver() { viewModel.loadingStatus .subscribe(onNext: { [weak self] status in guard let self = self else { return } switch status { case .none: break case .loading: // インディケーターを出す処理 case .error(message): // エラーのインディケーターを出す処理 // 何らかの時間を待つ処理 ←ここが綺麗じゃない self.viewModel.loadingStatus.accept(.dismiss) // ←ここが綺麗じゃない case .dismiss: // インディケーターを消す処理 } }) .disposed(by: disposeBag) }
のような形になってしまい、あまり綺麗な形で運用できていないので、何かアドバイス等あれば教えてください。 本当は↓こうしたい
AnySession .subscribe(onNext: { [weak self] _ in guard let self = self else { return } self.loadingStatus.accept(.dismiss) }, onError: { [weak self] _ in self.loadingStatus.accept(.error(message: "エラーが発生しました")) }) // onErrorの場合だけ数秒待って self.loadingStatus.accept(.dismiss)をしたい .disposed(by: disposeBag)