Swift一个小例子带你了解Combine中多重订阅不丢失(auto replay)的方法

引子

Combine中虽然有众多内置Operators,但是要想实现对同一个Publisher多次订阅,且结果不丢失还是比较棘手的,除非实现自定义Publisher,但这不是今天我们的话题 😉

在这里插入图片描述

什么是多重订阅?

多重订阅就是多个订阅者订阅同一个Publisher。

什么是多重订阅不丢失?

不丢失指的是,在有多个订阅者的情况下,无论发生何种情况都可确保每个订阅者都可以接收到每一个消息。

即这是一个自动重发的机制,因为正常情况下Publisher源只会发布一次消息,绝不会为某个订阅者再发一次,你错过了只有怪你自己哦。

举个栗子

拿从网络读取Web数据这个异步操作来说,如果有订阅者在数据返回之后再订阅,它显然无法接收到之前发送的数据:

第一步: 创建发布者

第二步: 订阅者1订阅

第三步: 发布者返回Web数据

第四步: 订阅者1接收到数据

第五步: 订阅者2订阅(接收不到之前的数据)

如上所示,除非使用某种缓存再重发机制,订阅者2就会丢失之前的那次数据。

let url = URL(string: "https://www.csdn.net")!

let p = URLSession.shared.dataTaskPublisher(for: url)
    .share()
    .map(\.data)

	var subscriptions = [AnyCancellable]()

	// 模拟延时一段时间后再订阅
	DispatchQueue.main.asyncAfter(deadline: .now()+5.0){
	    p.sink(receiveValue: {
	    	// 订阅者2不会收到数据
	        print("2: \($0)")
	    }).store(in: &subscriptions)
	}
	
	// 订阅者1立即订阅
	p.sink(receiveValue: {
		// 订阅者1可以收到数据
	    print("1: \($0)")
	}).store(in: &subscriptions)

上面这段简单的代码演示了多重订阅丢失的问题.

那么如何较简单的解决上述问题呢?

在这里插入图片描述

多播前来拯救

Combine中有一个multicast(多播)操作符,用它可以较好地满足上面的问题。

multicast操作符有一个重要的特性,按需手动刷新消息槽.

我们可以在需要时主动为所有订阅者发送消息,而不是让发布者“为所欲为”任性发送…

在这里插入图片描述

废话打住,上代码:

为创建的发布者链接multicast操作符:

let p = URLSession.shared.dataTaskPublisher(for: url)
    .share()
    .map(\.data)
    .multicast {PassthroughSubject<Data,URLError>()}

注意其返回另一个Publisher,其中的泛型类型不能错!

现在运行代码,是神马结果???

结果就是不会有任何订阅者收到数据,上面说了multicast之后必须由你手动刷新消息槽。

接着在创建订阅者2的结尾加上一句:

// 手动刷新消息槽
p.connect()
    .store(in: &subscriptions)

再次运行代码,你会发现两个订阅者都收到的消息,我们的目标就达到了 😉

总结

Combine中的操作符有很多,要想Combine用的好,用的妙,操作符必须烂熟于胸啊…

再会啦 😉

在这里插入图片描述

大熊猫侯佩 CSDN认证博客专家 Swift Objective-C Xcode
非自由程序员,CSDN博客认证专家。
CSDN汇编板块版主, CSDN其他开发语言大版版主。

对App、以及Cocos2D、SpriteKit游戏开饶有兴趣。目前常用的语言是ObjC、Swift、Ruby等。不过看到编程艺术、ASM、逆向和C时依然欲罢不能。虽然不是,但喜欢黑客的思维和哲学,认为社会工程学很酷,但还没有实际用来撩过妹。
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页
实付 39.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值