仅当特定的Observable发生变化时,才如何合并最新

时间:2019-02-19 02:02:34

标签: swift rx-swift

我对RxSwift非常陌生,并尝试执行以下操作:

我的应用程序需要启用“元素”的选择,其中选择模式可以是single选择(新选择替换旧选择)或multiple,其中将选择添加到任何旧选择

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

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

我有三个现有的主题:selectionModeSubject是一个BehaviorSubject,包含singlemultiple枚举。 selectSubject代表用户请求的新选择,它是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时触发。

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

任何提示将不胜感激。

1 个答案:

答案 0 :(得分:0)

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)