RxSwiftでUIActivityIndicatorViewのローディングを実装する

概要

RxSwiftでUIActivityIndicatorViewをローディングさせたかったがやり方が分からなかったのでメモとして残してみます。 クラス構成は適当ですが、MVVMを意識しています。

ViewModelの実装

ViewModel.swift

import RxSwift
import RxCocoa

class ViewModel {

    final let isAnimating = Variable(false)
    
    func showIndicator() {
        isAnimating.value = true
    }
    
    func hiddenIndicator() {
        isAnimating.value = false
    }
}

ViewControllerの実装

ViewController.swift

import RxSwift
import RxCocoa

class ViewController {
    @IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!  // IBOutletの接続は行う事

    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        
          // isAnimatingのフラグをIndicatorのisAnimatingに連携させる
        viewModel.isAnimating.asDriver()
            .drive(activityIndicatorView.rx.isAnimating)
            .disposed(by: disposeBag)
        // isAnimatingのフラグをIndicatorのisHiddenに連携させる
        viewModel.isAnimating.asDriver()
            .map { !$0 }
            .drive(activityIndicatorView.rx.isHidden)
            .disposed(by: disposeBag)
    }

    @IBAction func tapShowIndicator() {
        showIndicator() 
    }

    @IBAction func tapHiddenIndicator() {
        hiddenIndicator() 
    }
}

説明

ViewModelでフラグをVariableと宣言します。Variable(false)とする事でRxのストリームでfalseのフラグが流れるようになります。 ViewController側でそれをキャッチ(.asDriver())してbind(.drive(activityIndicatorView.rx.isHidden))させることによって フラグから@IBOutletへの接続(連携)実装が可能になります。

あとはViewController側でUIButtonをtapShowIndicatortapShowIndicatorをそれぞれ紐づけて シミュレータでボタンをタップすればindicatorがクルクル回るようになります。

もちろん、UIButtonもRxSwift実装すれば@IBActionが不要になりますがそれはまた別の機会で説明します。