Search code examples
iosswiftcombinepublishersubscriber

How to access the subscriptions from the given publisher? (combine kit)


Is there any way to get the subscriptions by accessing the publisher?

In the below example, I created a publisher, and had it subscribed by two subscribers and had the publisher send a value.

Here in this simple scenario, all works are thrown together in a couple of lines of code. It is easy to notice who subscribed the publisher. In real world application, however, each work is compartmentalized and hard to notice the subscribers from the publisher's standpoint.

So, does a publisher has properties to get access to the subscribers or subscriptions? Or, do you suggest a design pattern to make publisher-subscriber data flow more obvious?

final class IntSubscriber: Subscriber {

  typealias Input = Int
  typealias Failure = Never

  func receive(subscription: Subscription) {
      print("receive subscription")
    subscription.request(.max(3))
  }

  func receive(_ input: Int) -> Subscribers.Demand {
    print("Received value", input)
    return .none
  }

  func receive(completion: Subscribers.Completion<Never>) {
    print("Received completion", completion)
  }
}

let subject = PassthroughSubject<Int, Never>()
let subscriber1 = IntSubscriber()
let subscriber2 = IntSubscriber()
subject.subscribe(subscriber1)
subject.subscribe(subscriber2)

// send a value without knowing who might get the value?
subject.send(3)

Solution

  • No, you cannot ask a publisher for its existing subscribers or subscriptions.

    As for design patterns, I'm not sure what your goal is.

    • If you want to be able to find the subscribers while debugging, then I'd say Combine is lacking in that department. Maybe Apple will delight us with better debugging tools at next week's WWDC.

    • If you want to be able to statically see the overall flow, then I don't think you need any special patterns. You need to apply the same skills you would use to write a clear, understandable program that doesn't use Combine. Consider that other, much older APIs like NotificationCenter provide a very similar decoupling of signal emitters and signal receivers.

    Keep in mind that Combine is “just” Apple's implementation of the Rx (Reactive Extensions) paradigm. Since Apple is so late to the Rx game (Microsoft released Rx.NET 1.0 in 2011!), there is a lot of advice available on how to use Rx that is applicable to Combine.