如何仅在特定 Observable 发生更改时合并最新

How to combineLatest only when a particular Observable has changed

我是 RxSwift 的新手,正在尝试执行以下操作:

我的应用程序需要启用 "Elements" 选择,其中选择模式可以是 single 选择(新选择替换旧选择)或 multiple,其中添加选择任何旧的选择。

single模式下,如果新选择是旧选择,那么我的选择结果必须为空(通过选择相同的元素来切换选择)。

multiple模式下,如果新选择是旧选择的一部分,则新选择的元素将从当前选择中移除。

我有三个现有主题:selectionModeSubject 是一个包含 singlemultiple 枚举的 BehaviorSubjectselectSubject表示用户请求的新选择,是一个PublishSubject。最后,currentSelectionSubject,一个 BehaviorSubject 包含当前选择的元素集。

我试图让 currentSelectionSubject 包含 selectSubject 触发后的结果选择。

这是我的:

Observable
        .combineLatest(selectionModeSubject, selectSubject, currentSelectionSubject) { (mode, newSelection, currentSelection) -> Set<Element> in
            switch mode {
            case .single:
                if currentSelection.contains(newSelection) {
                    return Set([newSelection])
                } else {
                    return Set<Element>()
                }
            case .multiple:
                if currentSelection.contains(newSelection) {
                    return currentSelection.filter({ (element) -> Bool in
                        return element != newSelection
                    })
                } else {
                    return currentSelection.union(Set([newSelection]))
                }
            }
        }
        .bind(to: currentSelectionSubject)
        .disposed(by: disposeBag)

我的新手 RxSwift 状态放大了这个问题,这个观察代码可能会在 selectionModeSubjectcurrentSelectionSubject 触发时触发。我只想在 selectSubject 改变时触发它。

我试图在 selectSubject 上插入一个 .distinctUntilChanged(),但我似乎无法理解它。

如有任何提示,我们将不胜感激。

withLatestFrom 是要走的路。

selectSubject.withLatestFrom(
  Observable
    .combineLatest(selectionModeSubject, currentSelectionSubject)) { newSelection, pair in
  let (mode, currentSelection) = pair

  return (mode, newSelection, currentSelection)
}.map { (mode, newSelection, currentSelection) -> Set<Element> in
  switch mode {
  case .single:
    if currentSelection.contains(newSelection) {
      return Set([newSelection])
    } else {
      return Set<Element>()
    }
    case .multiple:
      if currentSelection.contains(newSelection) {
        return currentSelection.filter({ (element) -> Bool in
          return element != newSelection
        })
      } else {
        return currentSelection.union(Set([newSelection]))
      }
    }
  }
  .bind(to: currentSelectionSubject)
  .disposed(by: disposeBag)