Home > Back-end >  Store subscription from custom Combine subscriber?
Store subscription from custom Combine subscriber?

Time:11-11

According to the swift combine documentation, the proper way to connect a subscriber to a publisher is with the publishers subscribe<S>(S) protocol extension method. Then the publisher creates a subscription and passes that subscription on to the subscriber. All's well and good so far.

What I can't seem to figure out is how to gain access to that subscription and retain it in the calling code. How is sink() implemented such that it can return that subscription? Unless I'm mistaken, the subscription is responsible for retaining its subscriber, which means I can't store a reference to the subscription in the subscriber. And since Subscription isn't class bound, it can't be weak.

CodePudding user response:

The cancellable retains the subscription (or possibly is the subscription. Remember Subscriptions are Cancellables.) So when you retain the Cancellable, you are retaining the subscription.

CodePudding user response:

Here's an example of how sink might be implemented

import Combine
import Foundation

extension Publisher {
    func mockSink(
        receiveValue: @escaping (Output) -> Void,
        receiveCompletion: @escaping (Subscribers.Completion<Failure>) -> Void) -> AnyCancellable {

            var result : AnyCancellable!
            let anySubscriber = AnySubscriber(
                receiveSubscription: { subscription in
                    subscription.request(.unlimited)
                    result = AnyCancellable({subscription.cancel()})
                },
                receiveValue: { (value : Output) in receiveValue(value); return .unlimited},
                receiveCompletion: receiveCompletion)

            subscribe(anySubscriber)
            return result
        }
}

var subscriptions = Set<AnyCancellable>()
["one", "two", "three"].publisher
    .mockSink(receiveValue: {debugPrint($0)}, receiveCompletion: {debugPrint($0)})
    .store(in: &subscriptions)

As you can see the ability to return an AnyCancellable arises from the magic of AnySubscriber which returns its subscription in a closure. AnySubscriber is a handy tool to have when implementing custom Publishers and it may be helpful if you want to implement your own Subscriber type. But basically a Subscriber only exposes the subscription if it is designed to.

  • Related