如果我有一个主题并从下面的许多地方订阅它,我应该使用 .share() 吗?或者 .share() 在这种情况下什么也不做?
let sampleSubject = CurrentValueSubject<String, Never>("")
sampleSubject.sink { print($0) }
sampleSubject.sink { print($0) }
sampleSubject.sink { print($0) }
sampleSubject.sink { print($0) }
Run Code Online (Sandbox Code Playgroud)
let sharedSampleSubject = sampleSubject.share()
sharedSampleSubject.sink { print($0) }
sharedSampleSubject.sink { print($0) }
sharedSampleSubject.sink { print($0) }
sharedSampleSubject.sink { print($0) }
Run Code Online (Sandbox Code Playgroud)
大多数发布者都是structs(值类型),因此当您订阅它们时,它实际上会创建管道的副本。
.share()为它们提供参考语义。但是,像PassthroughSubject和这样的主题CurrentValueSubject已经是类,所以在这种情况下,它不会执行任何操作。
但是,假设我们有一个管道,将一个值与计数器一起作为元组发布。这可以通过运算符来完成.scan:
let subject = PassthroughSubject<String, Never>()
let publisher = subject.scan((0, ""), { ($0.0 + 1, $1) })
Run Code Online (Sandbox Code Playgroud)
如果您订阅它并发送一些值,如下所示:
let c1 = publisher.sink { print("c1:", $0) }
subject.send("a")
subject.send("b")
Run Code Online (Sandbox Code Playgroud)
输出将是:
let subject = PassthroughSubject<String, Never>()
let publisher = subject.scan((0, ""), { ($0.0 + 1, $1) })
Run Code Online (Sandbox Code Playgroud)
但是,如果您再次订阅,计数器会发生什么情况呢?
let c2 = publisher.sink { print("c2:", $0) }
subject.send("c")
Run Code Online (Sandbox Code Playgroud)
由于我们没有使用.share,输出将是:
let c1 = publisher.sink { print("c1:", $0) }
subject.send("a")
subject.send("b")
Run Code Online (Sandbox Code Playgroud)
Scan第二个订阅者再次从 1 开始计数,因为它获得了初始值为 0 的新副本。
有了.share,就会是:
c1: (1, "a")
c1: (2, "b")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1253 次 |
| 最近记录: |