如何将 .share() 与主题一起使用 [Swift Couple]

use*_*004 1 swift combine

如果我有一个主题并从下面的许多地方订阅它,我应该使用 .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)

New*_*Dev 7

大多数发布者都是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)