【RxSwift】viewWillAppear等が呼ばれた時のトリガーを作ってみる

Saturday, April 23, 2016

すっごい簡単なものですが、 viewWillAppear: が呼ばれたのをトリガーにするObservableを定義してみました。
これで、 viewWillAppear がcallされた時をトリガーにして、リロード処理をする等できます。

定義してみる

内容はとても簡単で、extensionでNSObjectに対して実装されている、 rx_sentMessage(:)_ を使ってあげるだけです。
引数にselectorを渡してあげることで、その関数が呼ばれた時を捕捉することができます。

import Foundation
import UIKit

import RxSwift

extension UIViewController {

    private func trigger(selector: Selector) -> Observable<Void> {
        return rx_sentMessage(selector).map { _ in () }.shareReplay(1)
    }

    var viewWillAppearTrigger: Observable<Void> {
        return trigger(#selector(self.viewWillAppear(_:)))
    }

    var viewDidAppearTrigger: Observable<Void> {
        return trigger(#selector(self.viewDidAppear(_:)))
    }

    var viewWillDisappearTrigger: Observable<Void> {
        return trigger(#selector(self.viewWillDisappear(_:)))
    }

    var viewDidDisappearTrigger: Observable<Void> {
        return trigger(#selector(self.viewDidDisappear(_:)))
    }

}

ポイントとしては、 rx_sentMessage(:)_ で帰ってくる型が、Observable<[AnyObject]>なので、これを一度 _map_ を使って、Observable<Void>になるようにしてあげます。
_map_ の中の ()はVoidを表しています。

使ってみる

実際にはこんな感じで使います。

class SampleViewController: UIViewController {
    private let disposeBag = DisposeBag()
    func viewDidLoad() {
        super.viewDidLoad()
        viewWillAppearTrigger
            .subscribeNext { _ in
                print("viewWillAppear")
            }
            .addDisposableTo(disposeBag)
    }
}

さらに、初回表示時だけスキップしたいときは、

class SampleViewController: UIViewController {
    private let disposeBag = DisposeBag()
    func viewDidLoad() {
        super.viewDidLoad()
        viewWillAppearTrigger
            .skip(1)
            .subscribeNext { _ in
                print("viewWillAppear")
            }
            .addDisposableTo(disposeBag)
    }
}

と、skip(1)を加えてあげれば、次回以降(例えば、別の画面に遷移して戻ってきた時)だけ処理が走るようになります。

techSwiftRxSwiftTips

【RxSwift】concatとmergeの違いをサンプルを元に整理してみる

NSLocalizedStringでkeyが見つからない時はkeyではなくて指定した文字列を出力する