在 Swift Combine 中,"root" 对象总是一个 Subject 吗?

In Swift Combine, is the "root" object always a Subject?

Apple 在 Swift Combine 上的 WWDC 视频中,他们总是使用 NSNotificationCenter 作为消息的发布者。但是,Publisher 似乎没有任何实际按需发送消息的能力。该功能似乎在 Subject.

我假设 Subject 必须是任何 Publishers 链的根对象是否正确? Apple 提供了两个内置主题:CurrentValueSubjectPassthroughSubject.

但我假设我可以使用适当的协议编写自己的 Subject

在 Swift Combine 中,Publishers 是一种描述对象的协议,可以随时间传输值。

主题是知道如何命令式发送的扩展发布者。

Publisher 和 Subject 都不是具体的 类 实现;它们都是协议。

看看 Publisher 协议(记住 Subject 是一个扩展的 Publisher):

public protocol Publisher {

    associatedtype Output

    associatedtype Failure : Error

    func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input
}

要构建自定义发布者,您只需实施接收函数(并提供类型信息),您可以在其中访问订阅者。您将如何从发布者内部向该订阅者发送数据?

为此,我们查看订阅者协议以查看可用的内容:

public protocol Subscriber : CustomCombineIdentifierConvertible {
...

    /// Tells the subscriber that the publisher has produced an element.
    ///
    /// - Parameter input: The published element.
    /// - Returns: A `Demand` instance indicating how many more elements the subcriber expects to receive.
    func receive(_ input: Self.Input) -> Subscribers.Demand
}

只要您保存了对已连接的 any/all 个订阅者的引用,您的发布者就可以通过对订阅者调用 receive 轻松地将更改发送到管道中。但是,您必须自行管理订阅者和差异更改。

Subject 的行为相同,但不是将更改流式传输到管道中,它只是提供一个 send 函数供其他人调用。 Swift 提供的两个具体主题具有存储等附加功能。

TL;DR 更改不会发送给发布者,而是发送给订阅者。主题是可以接受一些输入的发布者。