为什么`subscribe(subject)`返回AnyCancellable但`subscribe(subscriber)`无效?

时间:2019-12-20 12:02:26

标签: swift combine

我正在使用Swift Combine,但两者之间没有区别

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

func subscribe<S>(_ subject: S) -> AnyCancellable where S : Subject, Self.Failure == S.Failure, Self.Output == S.Output

为什么一个返回AnyCancellable而另一个却Void呢?

我有一个自定义的Subscriber,因此使用它完全安全

myPublisher.subscribe(myCustomSubscriber)

无需处理AnyCancellable

2 个答案:

答案 0 :(得分:0)

一个期望Subscriber,另一个期望Subject。由于您的参数是订阅者,因此它将返回AnyCancellable

现在,根据该行的范围,您很有可能需要保留该AnyCancellable对象的引用。直接或通过调用store(:)。您将其保留下来,以便在发布任何“输出”或“失败”之前不会将其释放。

我不确定您要做什么,但这是一种罕见的情况,需要自定义订阅者。您通常可以只使用assignsink运算符来建立订阅者并将其附加到发布者。

答案 1 :(得分:0)

更新

作为下面的解释,您的自定义Subscriber(在下面的代码中我将其命名为MySubscriber)应实现Cancellable协议。现在,您可以通过将订阅添加到Set<AnyCancellable>来管理订阅。取消订阅者后,订阅也会被取消。


我也有同样的担忧。我有一个自定义订阅者Subscribers.MySubscriber,并且想要添加功能Publisher.mySubscriber(),就像Combine对Subscribers.SinkPublisher.sink()所做的那样。但是我不知道Publisher.sink()如何返回AnyCancellable。几分钟后,我想出一个解决方案Publisher.sink()的实现方式:

extension Publisher {
    public func mySink(receiveCompletion: @escaping ((Subscribers.Completion<Self.Failure>) -> Void), receiveValue: @escaping ((Self.Output) -> Void)) -> AnyCancellable {
        let sink = Subscribers.Sink<Self.Output, Self.Failure>(receiveCompletion: receiveCompletion, receiveValue: receiveValue)
        subscribe(sink)
        return AnyCancellable(sink)
    }
}

因此,自定义订阅者应遵循Cancellable,并保留订阅引用,以便在调用subsriber的cancel()时取消订阅,如下所示:

final class MySubscriber<Input, Failure: Error>: Subscriber, Cancellable {

    var subscription: Subscription?
    
    // ...
    
    init() {}

    func receive(subscription: Subscription) {
        // ...
        self.subscription = subscription
    }

    func receive(_ input: Input) -> Subscribers.Demand {
        // ...
        return .unlimited
    }

    func receive(completion: Subscribers.Completion<Failure>) {
        // ...
    }

    func cancel() {
        subscription?.cancel()
        subscription = nil
    }
}

所以我的函数Publisher.mySubscriber()将是:

extension Publisher {
    public func mySubscriber() -> AnyCancellable {
        let mySubscriber = MySubscriber<Output, Failure>()
        subscribe(mySubscriber)
        return AnyCancellable(mySubscriber)
    }
}