PublishSubjectを使いこなす

はじめに

RxSwiftを勉強し始めてまだ日が浅いですが、値を返す際にPublishSubjectを使うと便利です。

asObservableでObserbableにできるし、呼び出し先でsubscribeもできます。

PublishSubjectを使ってシンプルなアプリケーションを作成してみました。

PublishSubjectミニマムアプリ

今回作成したアプリは画面の文字が変わるだけのアプリです。

初めはstartという文字で3秒経過するとendという文字に変更させます。

ラベルの文字を変更するロジッククラス

start()とend()の中でstateSubject.onNext()を呼んでいますが、ここで状態が変わると、subscribeしているところにストリーム(処理)が流れます。

今回はViewController側でsubscribeします。

enum State {
    case start
    case end
}

class Logic {
    //PublishSubjectのメンバを作成しています、
    private let stateSubject =  PublishSubject<State>()
    
    //SubscribeさせるためにObservableとして外に公開する
    var stateChanged: Observable<State> {
        return stateSubject.share().asObservable()
    }
    
    func start() {
        stateSubject.onNext(.start)
    }
    func end() {
        stateSubject.onNext(.end)
    }
}

Subscribeして受け取る

起動するとlogic.start() が呼ばれ、3秒後にlogic.end()が呼ばれてラベルの文字が変わります。

class ViewController: UIViewController {
    
    @IBOutlet weak var label: UILabel!
    var logic = Logic()
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //PublishSubjectに変更があったらここに来る
        logic.stateChanged.observeOn(MainScheduler.instance).subscribe(onNext: {[weak self] state in
            self?.changeLabelText(state: state)
        }).disposed(by: disposeBag)
        //上の処理が呼ばれる
        logic.start()

        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            //上の処理が呼ばれる
            self.logic.end()
        }
    }
    func changeLabelText(state: State){
        switch  state {
        case .start:
            label.text = "start"
        case .end:
            label.text = "end"
        }
    }
}