反应式SWIFT链式信号发生器不会向下游发送已完成的信号

反应式SWIFT链式信号发生器不会向下游发送已完成的信号,swift,reactive-swift,Swift,Reactive Swift,因为我是反应式编程的新手,所以我有一个关于在ReactiveSwift中链接信号生产者的初学者问题。我的目标是创建一个信号生产者链,以测试我的一个流。在做信号发生器链接时,我遇到了一个障碍。如果我最内部的SignalProducer正在调用sendCompleted,它将不会传播到下游。这是一个在操场上的模拟代码 private func doSomethingWithString() -> SignalProducer<Int, Error> { return Sig

因为我是反应式编程的新手,所以我有一个关于在ReactiveSwift中链接信号生产者的初学者问题。我的目标是创建一个信号生产者链,以测试我的一个流。在做信号发生器链接时,我遇到了一个障碍。如果我最内部的SignalProducer正在调用sendCompleted,它将不会传播到下游。这是一个在操场上的模拟代码

  private func doSomethingWithString() -> SignalProducer<Int, Error> {
  return SignalProducer<String, Error> {observer, _ in
    observer.send(value: "Hello")
  }.flatMap(.latest, doSomethingWithInt(string:))
}

private func doSomethingWithInt(string: String) -> SignalProducer<Int, Error> {
  return SignalProducer<Int, Error> { observer, _ in
    observer.send(value: 2)
    observer.sendCompleted()
  }
}

func test() -> SignalProducer<Int,Error> {
  return doSomethingWithString()

}
func leGo() {

  test().start { (event) in
    switch event {
    case .completed:
      print("DONE")
    case .value(let value):
      print("WE HAVE A VALUE: \(value)")
    case.interrupted:
      print("INTERRUPTED")
    case .failed(let error):
      print("FAILED \(error)")
    }
  }
}

leGo()
private func doSomethingWithString()->SignalProducer{
返回信号发生器{observer,{in
发送(值:“你好”)
}.flatMap(.latest,doSomethingWithInt(字符串:))
}
私有函数doSomethingWithInt(字符串:字符串)->SignalProducer{
返回信号发生器{observer,{in
发送(值:2)
observer.sendCompleted()
}
}
func test()->SignalProducer{
返回doSomethingWithString()
}
func乐高(){
test().在中启动{(事件)
切换事件{
案件.已完成:
打印(“完成”)
案例值(let值):
打印(“我们有一个值:\(值)”)
案例1:
打印(“中断”)
案例。失败(let错误):
打印(“失败\(错误)”)
}
}
}
乐高
在这个代码段中,值按预期打印“Wehavevalue2”,但从未执行completed,因此从未打印“DONE”。
如果有人能解释为什么会这样,以及如何正确地做到这一点,我将不胜感激。我可以通过在
doSomethingWithString
中调用
sendCompleted()
使其工作,但由于我的原始流有两个以上的方法,我不想在每个方法中编写它。另外,
.take(first:1)
对我来说是一个听起来很奇怪的选项,因为我真的不想通过整个链条来获取一件物品。相反,如果可能的话,我希望在一次完成中在一个地方终止整个流。

flatMap的目的是将每个传入值转换为一个新的生产者,然后根据某种策略将这些内部生产者的值展平为一个流。当一个内部生产者完成时,它不会发送一个已完成的事件,原因很简单,您可以有多个内部生产者,如果它在其一个内部生产者完成时完成,您将丢失所有其他内部生产者的值

因此,答案是,如果您希望整个流完成,您的外部生产者必须发送一个已完成的事件

下面是一个常见的
flatMap
示例,希望能说明
flatMap
的工作原理:

let searchResults = searchText
    .flatMap(.latest) { text in
        performSearch(for: text)
    }
searchResults
信号意味着每次用户更改搜索文本时都会使用新结果进行更新。因此,您不希望流仅仅因为其中一个搜索已完成而完成;您希望在用户更改文本时启动新搜索并更新结果

您可以为
SignalProducer
编写某种帮助器初始值设定项,它使用
take(first:1)
在单个值之后自动完成,但更惯用的做法是让所有生产者在完成后正确地发送完成事件