Swift Combine:这些多播功能是什么用途,以及如何使用它们



在https://developer..apple.com/documentation/combine/publisher中遇到"与多个订户"部分遇到的一些组合问题。

func multicast<S>(() -> S) -> Publishers.Multicast<Self, S>
func multicast<S>(subject: S) -> Publishers.Multicast<Self, S>

但是,当我试图确认发送给多个订户时需要进行多播的假设时,我发现在尝试此操场代码时,这不是必需的(从https://github.com/avdlee/combineswiftplayground进行了修改/blob/master/combine.playground/pages/combining publishers.xcplaygroundpage/contents.swift((Xcode版本11.0 Beta 3(11M362V(以10.14.5运行(:

>
enum FormError: Error { }
let usernamePublisher = PassthroughSubject<String, FormError>()
let passwordPublisher = PassthroughSubject<String, FormError>()
let validatedCredentials = Publishers.CombineLatest(usernamePublisher, passwordPublisher)
    .map { (username, password) -> (String, String) in
        return (username, password)
    }
    .map { (username, password) -> Bool in
        !username.isEmpty && !password.isEmpty && password.count > 12
    }
    .eraseToAnyPublisher()
let firstSubscriber = validatedCredentials.sink { (valid) in
    print("First Subscriber: CombineLatest: Are the credentials valid: (valid)")
}
let secondSubscriber = validatedCredentials.sink { (valid) in
    print("Second Subscriber: CombineLatest: Are the credentials valid: (valid)")
}
// Nothing will be printed yet as `CombineLatest` requires both publishers to have send at least one value.
usernamePublisher.send("avanderlee")
passwordPublisher.send("weakpass")
passwordPublisher.send("verystrongpassword")

此打印:

First Subscriber: CombineLatest: Are the credentials valid: false
Second Subscriber: CombineLatest: Are the credentials valid: false
First Subscriber: CombineLatest: Are the credentials valid: true
Second Subscriber: CombineLatest: Are the credentials valid: true

因此,似乎不需要多播来解决多个订户。还是我错了?

那么,这些多播功能是什么用途,我将如何使用它们?一些示例代码很好。

谢谢,

lars

PassThroughSubject不是一个很好的示例,因为它是一类,并为您提供参考语义。因此,在简单的情况下,两种订户可以直接订阅它,并在主体发出时同时接收相同的值。

,但这是一个更好的测试案例(受爱与可可的讨论的启发(:

    let pub1 = Timer.publish(every: 1, on: .main, in: .default).autoconnect()
    let sub = CurrentValueSubject<Int,Never>(0)
    let scan = sub.scan(10) {i,j in i+j}
    pub1.sink { _ in let i = sub.value; sub.value = i+1 }.store(in:&storage)
    scan.sink { print("a", $0) }.store(in:&storage)
    delay(3) {
        scan.sink { print("b", $0) }.store(in:&self.storage)
    }

当第二个sink作为该管道的新订户出现时,这绝对奇怪的结果:

a 10
a 11
a 13
a 16
b 13
a 20
b 17
a 25
b 22
a 31
b 28
a 38
b 35

下沉的ab彼此之间获得了不同的数字,因为scan是一个结构。如果我们希望他们获得相同的数字,我们可以使用多播:

    let scan = sub.scan(10) {i,j in i+j}.multicast {PassthroughSubject()}.autoconnect()

产生

a 10
a 11
a 13
a 16
a 20
b 20
a 25
b 25

是连贯的。

但是,仍然没有证明您需要multicast,因为您可以通过说.share()来完成相同的事情。我不清楚multicastshare之间的区别。

Swift论坛的答案/参考意味着多播方法旨在在.share((operator上构建。来自菲利普的帖子:

在这种情况下,它用于将上游连接到一个passthroughSubject,然后自动连接。通常,当订阅者收到订阅时,它将取消第一个订阅的任何其他订阅,多播给了此行为并处理多个订阅。

实际上,如果要通过组合中的多个管道拆分流和多播事件更新,则最务实的方法是创建一个@pelly属性,并使用.assign((或内部或内部的任何上游管道更新它。

相关内容

  • 没有找到相关文章

最新更新