RxCocoa でクラスの特定のメソッドをフックする


以前書いた ReactorKit の概要編のサンプル実装をしている際に、「ViewWillAppear で処理を行いたんだけど、rx で呼び出せないかな〜」と思っていたら、RxCocoa にはクラスの特定の関数をフックするプロパティが用意されていたのを最近知ったのでちょこっと使ってみようと思います。

提供されている関数

用意されている関数は下記の2つがあり、sentMessage がメソッドが呼ばれた時に通知され、methodInvoked がメソッドの処理が完了した直後に通知されます。

rx.sentMessage(Selector)
rx.methodInvoked(Selector)

使ってみる

sentMessagemethodInvoked を使ったサンプルコードが下記になります。

rx.sentMessage(#selector(viewWillAppear(_:)))
    .subscribe(onNext: { _ in
        print("viewWillAppearが呼ばれた直後です")
    })
    .disposed(by: disposeBag)

rx.methodInvoked(#selector(viewWillAppear(_:)))
    .subscribe(onNext: { _ in
        print("viewWillAppearの処理が終わった直後")
    })
    .disposed(by: disposeBag)

また、当然ですが下記のように自分で定義した関数もフックすることができ @IBAction のメソッドなんかも問題なくフックできます。

rx.sentMessage(#selector(hoge))
    .subscribe(onNext: { _ in
        print("hogeが呼ばれた直後です")
    })
    .disposed(by: disposeBag)

余談ですが、ReactorKit の StoryboardView を使った際に呼ばれる bind(reactor:) メソッドの際に sentMessagemethodInvoked でフックしようとしても通知されないので注意が必要です。理由は、StoryBoardView プロトコルで定義されている bind(reactor:) メソッドは ViewDidLoad の後に呼ばれるためです。このように、View の初期化時に処理したい場合は下記のように記述します。

  func bind(reactor: MyReactor) {
     Observable.just(Void())
  }

参考