Combine - 订阅者在第二次订阅时被静默取消

Combine - Subscriber gets cancelled silently when subscribing a second time

我正在尝试用 Combine 替换委托模式。

我的应用程序的架构是 VIPER,因此我需要将接收器订阅者从一个模块传递到另一个模块。用例是我有来自模块 A(列表)的数据需要显示给模块 B(详细视图),模块 B 也可以更新数据,所以我也需要将其返回给模块 A。

对于委托,它工作正常,但是当我使用接收器订阅者时,我遇到了问题。

我第一次从模块 A 转到模块 B,我传递订阅者,然后将它订阅到发布者(从模块 B),它运行良好,模块 A 中的订阅者接收来自模块 B 的所有事件。

但是当关闭模块 B 并再次从 A 路由到 B 时,订阅者在尝试再次订阅时立即收到取消事件:接收订阅:(PublishedSubject) ... 接收取消...

我做了一个非常简单的例子来说明发生了什么:

模块A:

class ViewController_A: UIViewController {
    
    var subscriber: AnySubscriber<String, Never>!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        createSubscriber()
    }
    
    func createSubscriber() {
        let subscriber = Subscribers.Sink<String, Never>(
            receiveCompletion: { completion in
                print(completion)
            }, receiveValue: { value in
                print(value)
            })
        self.subscriber = AnySubscriber(subscriber)
    }
    
    func showViewControllerB() {
        let viewControllerB = ViewControllerB()
        viewControllerB.passSubscriber(AnySubscriber(subscriber))
    }
}

模块 B:

protocol MyProtocol {
    var publisher: Published<String>.Publisher { get }
    func passSubscriber(_ subscriber: AnySubscriber<String, Never>)
}

class ViewController_B: UIViewController, MyProtocol {
    
    @Published var word: String = "House"
    var publisher: Published<String>.Publisher { $word }
    
    func passSubscriber(_ subscriber: AnySubscriber<String, Never>) {
        publisher
            .print()
            .subscribe(subscriber)
    }
    
    func dismiss() {
        dismiss(animated: true)
    }
}

路由时..

let viewControllerA = ViewController_A()
viewControllerA.showViewController_B() // When presenting B for the first time, receiving events here
// Dismiss B here...
viewControllerA.showViewControllerB() // When presenting B again (hence subscribing again), the subscription gets cancelled here without receiving any events/values

我注意到一些有趣的事情。当我每次路由到模块 B 时都重新创建订阅者而不是在 viewDidLoad 中只创建一次,它似乎工作正常,但我不确定为什么.

这是否意味着订阅者一旦订阅了另一个发布者就不能订阅另一个发布者,即使之前的发布者已经不存在了?

如何让它在我的授权案例中发挥作用?

When I create the subscriber again everytime I route to module B instead of creating it only one time in viewdidload, it seems to work okay

正确,因为这正是您应该做的。

已订阅然后取消/完成的订阅者已 结束,就像已订阅然后取消/完成的发布者已 结束。这些是轻量级对象,创建是为了促进两个“真实”端点之间的通信。当端点之一结束时,通信结束。

因此,如果您需要一个新的通信管道,您只需创建一个新的发布者/订阅者。