In Swift Combine, Publishers are a protocol describing an object which can transmit values over time.
A Subject is an extended publisher which knows how to send imperatively.
Neither Publisher nor Subject are concrete classes with implementation; they are both protocols.
Take a look at the Publisher protocol (and remember that a Subject is an extended 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
}
To build a custom publisher you need only implement the receive function (and provide type information), in which you are given access to a subscriber. How would you send data to that subscriber from WITHIN the publisher?
For this we look at the Subscriber protocol to see what's available:
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
}
As long as you've saved a reference to any/all subscribers which have connected, your publisher can easily send changes into the pipeline by calling receive on the subscriber. However, you'll have to manage subscribers and diff changes on your own.
A Subject behaves the same but instead of streaming changes into the pipeline, it simply provides a send function for someone else to call. The two concrete Subjects that Swift provides have additional features like storage.
TL;DR changes aren't sent to publishers they're sent to subscribers. Subjects are publishers that can accept some input.