Combine 框架,从0到1 —— 5.Combine 中的 Subjects
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 —— 5.Combine 中的 Subjects。
内容概览
- 前言
- PassthroughSubject
- CurrentValueSubject
- Subject 作为订阅者
- 常见用法
- 总结
前言
正所谓,工欲善其事,必先利其器。在开始使用 Combine 进行响应式编程之前,建议您先了解 Combine 为您提供的各种发布者(Publishers)、操作符(Operators)、订阅者(Subscribers)。
Subject 是一类比较特殊的发布者,因为它同时也是订阅者。Combine 提供了两类 Subject :PassthroughSubject 和 CurrentValueSubject。
如果您想了解更多 Publishers 的用法和注意事项,可以阅读:Combine 框架,从0到1 —— 5.Combine 提供的发布者(Publishers)
PassthroughSubject
PassthroughSubject 可以向下游订阅者广播发送元素。使用 PassthroughSubject 可以很好地适应命令式编程场景。
如果没有订阅者,或者需求为0,PassthroughSubject 就会丢弃元素。
示例代码:
final class SubjectsDemo {
private var cancellable: AnyCancellable?
private let passThroughtSubject = PassthroughSubject<Int, Never>()
func passThroughtSubjectDemo() {
cancellable = passThroughtSubject
.sink {
print(#function, $0)
}
passThroughtSubject.send(1)
passThroughtSubject.send(2)
passThroughtSubject.send(3)
}
}
输出内容:
passThroughtSubjectDemo() 1
passThroughtSubjectDemo() 2
passThroughtSubjectDemo() 3
CurrentValueSubject
CurrentValueSubject 包装一个值,当这个值发生改变时,它会发布一个新的元素给下游订阅者。
CurrentValueSubject 需要在初始化时提供一个默认值,您可以通过 value 属性访问这个值。在调用 send(_:) 方法发送元素后,这个缓存值也会被更新。
示例代码:
final class SubjectsDemo {
private var cancellable: AnyCancellable?
private let currentValueSubject = CurrentValueSubject<Int, Never>(1)
func currentValueSubjectDemo() {
cancellable = currentValueSubject
.sink { [unowned self] in
print(#function, $0)
print("Value of currentValueSubject:", self.currentValueSubject.value)
}
currentValueSubject.send(2)
currentValueSubject.send(3)
}
}
输出内容:
currentValueSubjectDemo() 1
Value of currentValueSubject: 1
currentValueSubjectDemo() 2
Value of currentValueSubject: 2
currentValueSubjectDemo() 3
Value of currentValueSubject: 3
Subject 作为订阅者
示例代码:
final class SubjectsDemo {
private var cancellable1: AnyCancellable?
private var cancellable2: AnyCancellable?
private let optionalCurrentValueSubject = CurrentValueSubject<Int?, Never>(nil)
private func subjectSubscriber() {
cancellable1 = optionalCurrentValueSubject
.sink {
print(#function, $0)
}
cancellable2 = [1, 2, 3].publisher
.subscribe(optionalCurrentValueSubject)
}
}
optionalCurrentValueSubject 可以作为一个订阅者去订阅序列发布者 [1, 2, 3].publisher 发送的元素。
输出内容:
subjectSubscriber() nil
subjectSubscriber() Optional(1)
subjectSubscriber() Optional(2)
subjectSubscriber() Optional(3)
常见用法
在使用 Subject 时,我们往往不会将其暴露给调用方。这时候,可以使用 eraseToAnyPublisher 操作符来隐藏内部的 Subject。
示例代码:
struct Model {
let id: UUID
let name: String
}
final class ViewModel {
private let modelSubject = CurrentValueSubject<Model?, Never>(nil)
var modelPublisher: AnyPublisher<Model?, Never> {
return modelSubject.eraseToAnyPublisher()
}
func updateName(_ name: String) {
modelSubject.send(.init(id: UUID(), name: name))
}
}
外部调用者无法直接操控 ViewModel 内部的 Subject,这样可以让 ViewModel 更好地面对将来可能的改动。
外部调用者只需要知道 modelPublisher 是 AnyPublisher<Model?, Never> 类型的发布者即可,无论内部采用了 CurrentValueSubject 还是 PassthroughSubject 甚至是其他的发布者。
总结
相比于其他的发布者来说, Subject 是比较容易理解的,而且也是最常用到的。
只可惜,对比 Rx 提供的 Subject,Combine 中的 Subject 无法设置缓冲的大小。也许某天苹果会对此做出调整吧~
Combine 框架,从0到1 —— 5.Combine 中的 Subjects的更多相关文章
- Combine 框架,从0到1 —— 1.核心概念
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 1.核心概念. 内容概览 前言 核心概念 RxSwift Combine 总结 参考内容 ...
- Combine 框架,从0到1 —— 2.通过 ConnectablePublisher 控制何时发布
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 2.通过 ConnectablePublisher 控制何时发布. 内容概览 前言 使用 ma ...
- Combine 框架,从0到1 —— 3.使用 Subscriber 控制发布速度
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 3.使用 Subscriber 控制发布速度. 内容概览 前言 在发布者生产元素时消耗它们 使 ...
- Combine 框架,从0到1 —— 4.在 Combine 中使用通知
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中使用通知. 内容概览 前言 让通知处理代码使用 Combine 总结 ...
- Combine 框架,从0到1 —— 4.在 Combine 中使用计时器
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中使用计时器. 内容概览 前言 使用计时器执行周期性的工作 将计时器转换为计时 ...
- Combine 框架,从0到1 —— 4.在 Combine 中使用 KVO
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中使用 KVO. 内容概览 前言 用 KVO 监控改动 将 KVO 代 ...
- Combine 框架,从0到1 —— 4.在 Combine 中执行异步代码
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中执行异步代码. 内容概览 前言 用 Future 取代回调闭包 用输出类型( ...
- Combine 框架,从0到1 —— 5.Combine 提供的发布者(Publishers)
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 5.Combine 提供的发布者(Publishers). 内容概览 前言 Just Future D ...
- Combine 框架,从0到1 —— 5.Combine 常用操作符
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 5.Combine 常用操作符. 内容概览 前言 print breakpoint handleEve ...
随机推荐
- codeforce Round #605(Div.3)
A. Three Friends 题目链接 题目意思:有三个好朋友a,b,c.他们在一个坐标轴上,他们的位置分别是xa 和xb ,xc,他们三个人都可以往前或者往后走一步,只能走一步.问你他们走了(也 ...
- 起源seo为何要做seo培训
http://www.wocaoseo.com/thread-91-1-1.html 焦大,在2010年末左右开始接触seo,2011年3月份正式开始做seo,到如今做seo已经3年了,实话说我没有其 ...
- 深入了解v-model流程
v-model原理 vue中v-model是一个语法糖,所谓的语法糖就是对其他基础功能的二次封装而产生的功能.简单点说,v-model本身就是父组件对子组件状态以及状态改变事件的封装.其实现原理上分为 ...
- 微信小程序入门教程
首先请看demo 很简单的静态js就可以实现一款小程序开发. js.json.html.css四个核心文件 序言 开始开发应用号之前,先看看官方公布的「小程序」教程吧!(以下内容来自微信官方公布的「小 ...
- vue+elementUI+vue-i18n 实现国际化
在main.js同级建i18n文件夹,并里面建i18n.js.langs文件夹,langs文件夹下建en.js.cn.js目录如下: . ├── App.vue ├── assets │ └── ...
- jsp页面关于isELIgnored="false",页面无法解析数据问题
问题: 首先确定所取的集合里面是否有值,如果没有先检查集合 如果有,就再jsp页面头部添加: isELIgnored="false" 具体如下: <%@ page langu ...
- 一文吃透redis持久化,妈妈再也不担心我面试过不了!
持久化介绍 redis 提供了两种方式方式进行数据的持久化(将数据存储到硬盘中):第一种称为快照(snapshotting)RDB,它将某一时刻的所有数据都写入硬盘,所以快照是一次全量备份,并且存储的 ...
- Zabbix housekeeper processes more than 75% busy
原因分析 为了防止数据库持续增大,Zabbix有自动删除历史数据的机制,即housekeeper,而在频繁清理历史数据的时候,MySQL数据库可能出现性能降低的情况,此时就会告警. 一般来说,Zabb ...
- ELK入门及基本使用
预备知识-Restful 起源 在没有前后端分离概念之前,一个网站的完成总是“all in one”,在这个阶段,页面.数据.渲染全部在服务端完成,这样做的最大的弊端是后期维护,扩展极其痛苦,开发人员 ...
- 转载:Linux: What’s the difference between a soft link and a hard link?
Link:https://www.moreofless.co.uk/linux-difference-soft-symbolic-link-and-hard-link/ This example sh ...