gpt4 book ai didi

swift - ReactiveSwift 链式 SignalProducers 不会将完成的内容发送到下游

转载 作者:行者123 更新时间:2023-11-30 10:29:53 27 4
gpt4 key购买 nike

由于我是响应式(Reactive)编程的新手,所以我对在 ReactiveSwift 中链接 SignalProducers 有一些初学者的问题。我的目标是创建一个 SignalProducers 链,以测试我的一个流程。在进行 SignalProducer 链接时,我偶然发现了一个障碍。如果我最里面的 SignalProducer 正在调用 sendCompleted ,它将不会传播到下游。这是 Playground 中的模拟代码

  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()

在此片段中,值按预期打印“WE HAVE A VALUE 2”,但从未执行completed,因此永远不会打印“DONE”。如果有人解释为什么会这样以及如何正确地做到这一点,我将非常感激。我可以通过在 doSomethingWithString 中调用 sendCompleted() 来使其工作,但由于我的原始流有超过 2 个方法,我不想在每个方法中都编写它。另外 .take(first:1) 对我来说听起来很奇怪,因为我真的不想遍历所有链来获取 1 个项目。相反,如果可能的话,我想在一次完成中在一处终止整个流。

最佳答案

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

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

以下是 flatMap 常用的示例,希望能够说明 flatMap 为何以这种方式工作:

let searchResults = searchText
.flatMap(.latest) { text in
performSearch(for: text)
}

searchResults 信号旨在每次用户更改搜索文本时更新新结果。因此,您不会仅仅因为其中一个搜索完成就希望流完成;您希望在用户更改文本时启动新搜索并更新结果。

您可以为 SignalProducer 编写某种帮助程序初始化程序,它使用 take(first: 1) 在单个值之后自动完成,但更惯用的做法是所有生产者只需在完成后正确发送完成事件即可。

关于swift - ReactiveSwift 链式 SignalProducers 不会将完成的内容发送到下游,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59374282/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com