合并 - 订阅者在第二次订阅时被静默取消
Posted
技术标签:
【中文标题】合并 - 订阅者在第二次订阅时被静默取消【英文标题】:Combine - Subscriber gets cancelled silently when subscribing a second time 【发布时间】:2021-03-17 18:02:08 【问题描述】:我正在尝试用组合替换委托模式。
我的应用程序的架构是 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
中只创建一次,它似乎工作正常,但我不知道为什么。
这是否意味着订阅者一旦订阅了另一个发布者,就无法订阅另一个发布者,即使之前的发布者不再存在?
如何使它在我的委托案例中发挥作用?
【问题讨论】:
还有更多你没有给我们看的吗?你的 showViewControllerB 创建一个视图控制器,然后立即销毁它。 顺便说一句,我认为你的分析是非常正确的。您只需在 viewDidLoad 中创建一次订阅者,并且不能重复使用订阅者。每次 A 生成 B 时,您只需重新创建订阅者。 感谢您的回复!是的,很抱歉,这只是一个测试项目来展示正在发生的事情,但真实项目是在 Viper 上制作的,并且模块不会立即被破坏。 哦,我明白了,所以没有办法取消订阅订阅者以订阅新发布者? 没有需要。这些是轻量级对象。您正在两个 real 对象(视图控制器)之间建立通信管道。当通信因为其中一个对象消失而结束时,管道就结束了。现在你有了一个新的 ViewControllerB,创建一个新的管道。 【参考方案1】:当我每次路由到模块 B 时再次创建订阅者,而不是在 viewdidload 中只创建一次,它似乎工作正常
正确,因为这正是你应该做的。
订阅者已经订阅然后取消/完成是结束,就像发布者已经订阅然后取消/完成是结束。这些是轻量级对象,创建是为了促进两个“真实”端点之间的通信。当其中一个端点结束时,通信结束。
因此,如果您需要新的通信管道,您只需创建一个新的发布者/订阅者即可。
【讨论】:
感谢您的回答!那很有趣。我不明白的是,我从不取消或完成订阅者,那么为什么当我使用新发布者再次订阅它时它会立即取消? 我的印象是,您看到的是 first 管道取消,因为您正试图将其订阅者订阅到另一个管道。但我可能是错的。 谢谢@matt。即使我找不到与该问题相关的任何文档,我也会接受您的回答!无论如何,我都会尝试重新创建它,以确保它不会被取消。谢谢!!以上是关于合并 - 订阅者在第二次订阅时被静默取消的主要内容,如果未能解决你的问题,请参考以下文章