gpt4 book ai didi

swift - 了解Combine中的share()

转载 作者:行者123 更新时间:2023-12-03 15:43:38 30 4
gpt4 key购买 nike

众所周知,通常发布者是结构体。如果是一个类会发生什么变化?

假设我们有 1 个发布者发出 1 个值和 2 个订阅者订阅它。

let p1 = Just(20)
let s1 = p1.print().sink { _ in }
let s2 = p1.print().sink { _ in }

// s1 - receive value: (20)
// s2 - receive value: (20)

在打印日志中,我们可以看到两个订阅者都获得了值 (20)。

如果我们打开 share() 操作符的文档,我们会看到

share() - Returns a publisher as a class instance.



所以它只是将发布者的语义从值更改为引用。在我们的例子中,我们没有通过 p1发布者分配给任何函数或分配给任何对象,这就是为什么对我来说发布者是结构或类没有区别的原因...
但是如果我添加 share()运算符(operator)行为会有所不同, s2不会得到值(value)。
let p1 = Just(20).share() // !
let s1 = p1.print().sink { _ in }
let s2 = p1.print().sink { _ in }

// s1 - receive value: (20)

我看到了一些例子 URLSession.shared.dataTaskPublisher(\_: URL)或者一些“延迟”的发布者,当 s2也获得了值(value),但我仍然不清楚仅仅改变发布者的语义是如何以这种方式改变其行为的。

最佳答案

问题是您没有使用确实有所作为的管道。考虑这个示例(基于 Cocoa With Love 文章),其中第二个订阅者在发布者发布一段时间后上线:

let pub1 = Timer.publish(every: 1, on: .main, in: .default)
let c1 = pub1.connect()
let scan = Publishers.Scan(upstream: pub1, initialResult: 0) { (a, b) -> Int in
a + 1
}
scan.sink { print("a:", $0) }.store(in:&storage)
delay(3) {
scan.sink { print("b:", $0) }.store(in:&self.storage)
}

重点是,只有一个 scan并且它正在产生 1, 2, 3 当延迟后另一个订户出现时。订阅者会得到什么?它会回到我们现在的位置吗?不,我们得到了这个:
a: 1
a: 2
a: 3
a: 4
b: 1
a: 5
b: 2
a: 6
b: 3
...

所以实际上我们重新开始第二次订阅,因为发布者是一个新副本。但是如果我们将发布者提升为一个类,我们会得到完全不同的结果:
let pub1 = Timer.publish(every: 1, on: .main, in: .default)
let c1 = pub1.connect()
let scan = Publishers.Scan(upstream: pub1, initialResult: 0) { (a, b) -> Int in
a + 1
}
let scan2 = scan.share() // <--
scan2.sink { print("a:", $0) }.store(in:&storage)
delay(3) {
scan2.sink { print("b:", $0) }.store(in:&self.storage)
}

现在我们得到这个:
a: 1
a: 2
a: 3
a: 4
b: 4
a: 5
b: 5
a: 6
b: 6
a: 7
b: 7

显然,这是一个非常显着的差异。如果您的发布者是一个主题,您可以看到同样的事情,因为那是一个类,而不是一个结构体。

关于swift - 了解Combine中的share(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59593139/

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