如何过滤CombineLatest仅在一项更改时被触发?

时间:2018-10-28 20:20:53

标签: swift filter rx-swift combinelatest

我写了下面的小演示代码。 我制作了两个不同类型的PublishSubject。 当我更改任何页面触发器时 我只需要在 observable_page 中的一项更改时获取页面触发器。

class ViewController: UIViewController {

    func loadData(page: Int, keyword: String) -> Observable<[Int]> {
        let _result = Observable.of([1,2,3,4])
        return _result
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let observable_keyword = PublishSubject<String>()
        let observable_page = PublishSubject<Int>()
        let trigger_tap = PublishSubject<Void>()

        let tapObservable = trigger_tap.debug("trigger_tap", trimOutput: true)
        let stringObservable = observable_keyword.debug("stringObservable", trimOutput: true)
        let pageObservable = observable_page.debug("pageObservable", trimOutput: true)

        let request_call_trigger = Observable.combineLatest(tapObservable, pageObservable)
            .debug("request_call_trigger", trimOutput: true)

        let page = request_call_trigger
            .withLatestFrom(stringObservable) { ($0, $1) }
            .flatMap { ((_, _, page), keyword) in
                Observable.combineLatest(Observable.just(page), self.loadData(page: page, keyword: keyword)) { (pageNumber: $0, movies: $1) }
                    .materialize()
                    .filter { $0.isCompleted == false }
            }
            .share()

        observable_keyword.onNext("breaking bad")
        observable_page.onNext(1)

        trigger_tap.onNext(())

        observable_keyword.onNext("orange is new black")
        observable_keyword.onNext("orange")

    }

    let bag = DisposeBag()
}

我读了一些选项,感觉过滤器或忽略可能在这里起作用,但是由于我接下来需要它们的值,所以很困惑如何正确应用它。

2 个答案:

答案 0 :(得分:2)

如果您要寻找一个触发器,那么我认为您要寻找的运营商是withLatestFrom

observable2
  .withLatestFrom(observable1)

均值:仅当observable2更改时-获得其最新发射值以及observable1的最新发射值。

修改:如果您需要两个值,则可能需要提供一个resultsSelector

observable2
  .withLatestFrom(observable1) { ($0, $1) }

答案 1 :(得分:0)

您可以根据文档使用withLatestFrom

  

将两个可观察序列合并为一个可观察序列   将自我的每个元素与   第二个来源(如果有的话)

您的代码中的

request_call_trigger类型为Observable<(Void, Int>),您可以使用stringObservable将其与withLatestFrom中的最新值合并。这会产生另一个Observable<(((Void, Int), String)>

类型的元组

您可以在使用flatMap创建的元组上withLatestFrom,并通过使用$ 0.1的页面元组值将页面和关键字值传递给loadData方法,因此无需使用CombineLatest在flatMap中。

        let tapObservable = trigger_tap.debug("trigger_tap", trimOutput: true)
        let stringObservable = observable_keyword.debug("stringObservable", trimOutput: true)
        let pageObservable = observable_page.debug("pageObservable", trimOutput: true)

        let request_call_trigger: Observable<(Void, Int)> = Observable.combineLatest(tapObservable, pageObservable)
            .debug("request_call_trigger", trimOutput: true)

        _ = request_call_trigger
            .withLatestFrom(stringObservable) { ($0, $1) }
            .flatMap { [weak self] (request_page_tuple: (Void, Int), keyword: String) -> Observable<Event<[Int]>> in
                guard let strongSelf = self else {
                    return Observable.empty()
                }
                return strongSelf
                    .loadData(page: request_page_tuple.1, keyword: keyword)
                    .materialize()
                    .filter { !$0.isCompleted }
            }
            .share()