合并中的switchToLatest表现不符合预期

时间:2019-10-17 20:44:51

标签: swift combine

我一直在尝试从Combine中的RxSwift复制flatMapLatest,我在一些地方读到解决方案是使用.map(...).switchToLatest

我发现两者之间存在一些差异,并且不确定是否是我的实现/理解是问题所在。

在RxSwift中,如果上游可观察对象发出停止事件(完成或错误),则在flatMapLatest闭包中创建的下游可观察对象将继续发出事件,直到它们自身发出停止事件为止:

let disposeBag = DisposeBag()

func flatMapLatestDemo() {
    let mockTrigger = PublishSubject<Void>()
    let mockDataTask = PublishSubject<Void>()

    mockTrigger
        .flatMapLatest { mockDataTask }
        .subscribe(onNext: { print("RECEIVED VALUE") })
        .disposed(by: disposeBag)

    mockTrigger.onNext(())
    mockTrigger.onCompleted()

    mockDataTask.onNext(()) // -> "RECEIVED VALUE" is printed
}

“合并”中的同一设置的行为方式不同:

var cancellables = Set<AnyCancellable>()

func switchToLatestDemo() {
    let mockTrigger = PassthroughSubject<Void, Never>()
    let mockDataTask = PassthroughSubject<Void, Never>()

    mockTrigger
        .map { mockDataTask }
        .switchToLatest()
        .sink { print("RECEIVED VALUE") }
        .store(in: &cancellables)

    mockTrigger.send(())
    mockTrigger.send(completion: .finished)

    mockDataTask.send(()) // -> Nothing is printed, if I uncomment the finished event above then "RECEIVED VALUE" is printed
}

这是故意的吗?如果是这样,我们如何在Combine中复制flatMapLatest的行为?

如果不是故意的,我猜是雷达吗?

1 个答案:

答案 0 :(得分:0)

我已经通过sergdort使用了这个Swift实现:

func flatMapLatest<T: Publisher>(_ transform: @escaping (Self.Output) -> T) -> Publishers.SwitchToLatest<T, Publishers.Map<Self, T>> where T.Failure == Self.Failure {
    map(transform).switchToLatest()
}