Combine 中 Publisher、PassthroughSubject 和 CurrentValueSubject 的基本用法和区别

阅读须知:本文重点关注这三者的基本用处和区别,对于三者的详细说明在此不做介绍,有需要的读者推荐阅读:链接: Swift Combine 入门导读

1. Publisher 用法

在最简单的情况下我们使用 Publisher 和 sink 来实现一个简单的数据流

import Combine

let publisher = ["Here","we","go!"].publisher

let subscription = publisher.sink { value in
    print("subs received value: \(value)")
}

// 运行结果
//subs received value: Here
//subs received value: we
//subs received value: go!

在上面的案例中,publisher 初始化存储了一些数据,并且在被订阅后将这些数据逐个发出。这些数据发送完毕后,订阅者会收到一个完成的通知,并且这条管道会被关闭。当然,我们可以在下面再次使用 publisher.sink 订阅这些数据,这些数据会被再次逐个发送给新的订阅者。

2. PassthroughSubject 用法

想必大家看完上面的Publisher案例后都会产生疑问,因为我们在开发中大部分时间都是需要根据需要随时发布消息,而不是发布一条已经确定的数据流,我们如何实现随时插入数据呢,接下来我们就会用到 Subject。Subject 通常是一个中间代理,但是他不仅可以作为代理,还可以独立作为一个 Publisher 来发布消息。

独立作为Publisher示例代码,请仔细阅读注释理解
import Combine

// 初试化了一个 Subject,定义发布数据类型为 String 而且 Never 报错,更详细的用法请阅读文章开头的推荐链接
let pubSubject = PassthroughSubject<String, Never>()

// 在订阅之前 Send 的消息会丢失
pubSubject.send("订阅之前发送会丢失的数据")

let subscription = pubSubject.sink { value in
		print("subscription1 received value: \(value)")
}

pubSubject.send("Hello")
pubSubject.send("World!")

// 发送 (completion: .finished) 代表全部发完了,通知订阅结束
pubSubject.send(completion: .finished)
pubSubject.send("订阅已经收到了结束的通知,这条没用了!")

// 运行结果
//subscription1 received value: Hello
//subscription1 received value: World

在上面的例子里我们使用 PassthroughSubject 初试化了一个发布者,可以使用Send发布消息,但是需要注意的是,在被订阅之前,Send的数据都是无效的,都会丢失。

作为中间代理,使用 Publisher.subscribe(_Subject)
import Combine

let observeSubject = PassthroughSubject<String, Never>()

let subscription = observeSubject.sink { value in
        print("observeSubject received value: \(value)")
}

observeSubject.send("主动发布消息")

// 使用publisher.subscribe(Subject),可以将publisher的数据逐个发送到Subject里进行处理;
let publisher = ["Publisher发布消息","发布","消息"].publisher
publisher.subscribe(observeSubject)

// 因为在1中publisher的用法中我们说过,这些publisher数据发送完毕后,会发送一个完成的通知
// 就相当于上面的 publisher 还发了一个 .send(completion: .finished) ,因此这个订阅已经结束,后面主动发消息没用
observeSubject.send("这里发的消息收不到了,为什么呢,看上面注释")

在上面的例子里我们介绍了 publisher.subscribe(_Subject) , 其实开发中也很少用到,为了保持统一性和阅读性我们还是习惯用Subject.send来发送各种消息,和信号。

3. CurrentValueSubject

CurrentValueSubject 和 PassthroughSubject 完全类似,区别在于 CurrentValueSubject 会始终记录下之前发送的值,并在订阅后将当前的记录值发出去。

import Combine

let subject = CurrentValueSubject<String, Never>("初始化值,如果没被覆盖,订阅时会先收到我")

// 此时在订阅之前发的(最新的一个)消息就不会漏掉了。
subject.send("我就随便发一下,覆盖掉上次发送的值,被记录下来")

// 订阅时会先把当前记录的值发出去。
let subscription = subject.sink { value in
        print("observeSubject received value: \(value)")
}

subject.send("Hello World")

let publisher = ["Here","we","go!"].publisher
publisher.subscribe(subject)

// 运行结果
// subject received value: 我就随便发一下,会被记录下来,而且覆盖掉上次发送的值
// subject received value: Hello World
// subject received value: Here
// subject received value: we
// subject received value: go!

本文参考链接:

Swift Combine 入门导读: https://www.jianshu.com/p/a4f1a263eabb

强烈推荐:

用 Xcode Playground 学习 Combine:https://github.com/AvdLee/CombineSwiftPlayground

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值