Swift Combine — Subject Publishers(PassthroughSubject CurrentValueSubject)

本文主要介绍一下SubjectSubject 本身也是一个 Publisher,其定义如下:

public protocol Subject<Output, Failure> : AnyObject, Publisher {func send(_ value: Self.Output)func send(completion: Subscribers.Completion<Self.Failure>)func send(subscription: any Subscription)
}

从定义可以看到,Subject 暴露了三个 send 方法,外部调用者可以通过这些方法来主动地发布 output 值、failure 事件、 finished 事件以及subscription

Combine 内置提供了两种常用的 Subject 类型,分别是 PassthroughSubjectCurrentValueSubject,下面来分别看一下。

PassthroughSubject

PassthroughSubjectCombine框架中的一种Subject具体类型,它不持有任何值,将自己接收到的任何值简单的传递给下游的Subscriber

当我们要创建一个PassthroughSubject时,需要指定要发送的值的类型,然后使用send方法发送,任何的Subscriber都会收到这个值。因为它本身不持有值,所以如果下游没有Subscriber,那么这个值将废弃了。

  func testPassthroughSubjectPublisher() {let publish2 = PassthroughSubject<String, Error>()publish2.send("1")publish2.sink { completion inswitch completion {case .finished:print("---> Finished")case .failure(let error):print("---> Error: \(error.localizedDescription)")}} receiveValue: { value inprint("---> value is: \(value)")}.store(in: &cancellable)publish2.send("2")publish2.send(completion: .finished)}

上面代码中创建了PassthroughSubject实例publish2,并通过sink方法添加了订阅者,订阅后,随后通过send方法发送了2.finished事件,sink方法中对应的输出都正常。但是在添加sink方法之前发送的send("1")没有任何输出,就像上面说的,发送的时候还没有任何订阅者,发送的值就直接抛弃了。

输出结果:

---> value is: 2
---> Finished

作为Subject的具体实现,PassthroughSubject提供了一种方便的方法,使现有的命令式代码适应Combine模型。

CurrentValueSubject

CurrentvaluessubjectCombine框架中的一种Subject具体类型。它可以保存单个值,并在设置新值时向任何订阅者发布新值。
Currentvaluessubject在初始化的时候需要设置一个初始值。

let publisher = CurrentValueSubject<String, Error>("one")

当有订阅者订阅的时候会立即发送这个值。下面代码中当初始化CurrentValueSubjectViewModel的时候,则会直接输出“—> value is: one”

class CurrentValueSubjectViewModel: ObservableObject {init() {setUpPublisher()}func setUpPublisher() {let publisher = CurrentValueSubject<String, Error>("one")let cancelable = publisher.sink { completion inswitch completion {case .finished:print("---> Finished")case .failure(let error):print("---> Error: \(error.localizedDescription)")}} receiveValue: { value inprint("---> value is: \(value)")}}
}

下面代码中,在viewModel中实例化了一个CurrentValueSubject,并添加了subscriber,在SwiftUI界面添加了三个按钮,用来发送数据。

在发送数据的时候,可以通过send方法,也可以通过直接设置value的方法,效果都是一样的。

class CurrentValueSubjectViewModel: ObservableObject {private var cancellable = Set<AnyCancellable>()let publisher = CurrentValueSubject<String, Error>("one")init() {setUpPublisher()}func setUpPublisher() {publisher.sink { completion inswitch completion {case .finished:print("---> Finished")case .failure(let error):print("---> Error: \(error.localizedDescription)")}} receiveValue: { value inprint("---> value is: \(value)")}.store(in: &cancellable)}func sendMessage() {publisher.send("Hello World")publisher.value = "Swift Combine"}func sendError() {publisher.send(completion: .failure(NetworkError.invalidURL))}func sendFinished() {publisher.send(completion: .finished)}}struct CurrentValueSubjectDemo: View {@StateObject private var viewModel = CurrentValueSubjectViewModel()var body: some View {VStack {Button("Send Message") {viewModel.sendMessage()}Button("Send Finished") {viewModel.sendFinished()}Button("Send Error") {viewModel.sendError()}}.buttonStyle(BorderedProminentButtonStyle())}
}

当点击按钮时,输出如下:
在这里插入图片描述

关于Subject生命周期

Subject是有生命周期的,放发送了completion后(不管是finished还是error),Subject都不会再发送任何新值。

就上面的CurrentValueSubject为例,在发送一个value之后,就发送finished,然后在发送value就无效了。
在这里插入图片描述
PassthroughSubject亦是如此。所以当使用PassthroughSubjectCurrentValueSubject时,重要的是要考虑生命周期,并在明显没有任何值发送时关闭Subject

PassthroughSubject与CurrentValueSubject区别

首先这两个都是Subject的具体实现,都可以根据需要异步地无限地发出事件。这两个Subject的用法都比较简单,都作为Publisher发布数据,不过却别还是有的。

PassthroughSubject没有初始值,也不需要持有最近一次发布的值。
CurrentValueSubject可以为Publisher提供初始值,并通过更新 value属性自动发出事件。

网上有一个较为恰当的比喻:
PassthroughSubject就像一个门铃按钮。当有人按门铃时,只有当你在家时才会通知你。
CurrentValueSubject就像一个电灯开关。当你不在的时候灯是开着的,当你回家的时候你仍然会注意到它是开着的。

写在最后

本文主要介绍了PassthroughSubjectCurrentValueSubject的概念、使用以及一些区别,希望大家通过本文能对这两个Subject有个初步的了解和使用,文中如果有不对的地方,还望大家指正。

最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/29304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【漏洞复现】泛微OA E-Cology ln.FileDownload 任意文件读取漏洞

免责声明&#xff1a; 本文内容旨在提供有关特定漏洞或安全漏洞的信息&#xff0c;以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步&#xff0c;并非出于任何恶意目的。阅读者应该明白&#xff0c;在利用本文提到的漏洞信息或进行相关测…

JAVA开发 选择本地的文件,控制台输出选择的文件名

打开文件选择器对话框&#xff0c;控制台输出选择的文件 1、展示效果2、实现代码3、JFileChooser类 1、展示效果 2、实现代码 import javax.swing.*; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date;public class GenerateCompress {public sta…

强大的api管理系统Storm Core API_V1.1免授权源码

强大的api管理系统Storm Core API_V1.1免授权源码&#xff0c;带用户key和ip白名单功能 可设置付费操作等 更新日志 此次更新功能比较多 1.完善个人中心页面 2.完善注册登录页面 3.完善key功能 4.增加ip白名单功能 5.以及一些其他小小的美化 6.模板dxx的图片可单个自定…

AWS——01篇(AWS入门 以及 AWS之EC2实例及简单实用)AWS

AWS——01篇&#xff08;AWS入门 以及 AWS之EC2实例及简单实用&#xff09; 1. 前言 2. 创建AWS账户 3. EC2 3.1 启动 EC2 新实例 3.1.1 入口 3.1.2 设置名称 选择服务 3.1.3 创建密钥对 3.1.4 网络设置——安全组 3.1.4.1 初始设置 3.1.4.2 添加安全组规则&#xff08;开放新…

【Linux】MySQL下载与安装

1. 下载压缩包 官网下载 2. 解压 上传并解压好放在指定位置 创建soft文件夹 mkdir /soft上传文件&#xff0c;在该目录下再创建一个mysql文件夹&#xff0c;将安装包解压到新文件夹中 mkdir /soft/mysql-8.3.0 tar -xvf mysql-8.3.0-1.el9.x86_64.rpm-bundle.tar -C mysq…

C语言 | Leetcode C语言题解之第162题寻找峰值

题目&#xff1a; 题解&#xff1a; int findPeakElement(int* nums, int numsSize) {int ls_max0;for(int i1;i<numsSize;i){if(nums[ls_max]>nums[i]);else{ls_maxi;}}return ls_max; }

2024上海初中生古诗文大会倒计时4个月:单选题真题和独家解析

现在距离2024年初中生古诗文大会还有4个多月时间&#xff0c;我们继续来看10道选择题真题和详细解析&#xff0c;以下题目截取自我独家制作的在线真题集&#xff0c;都是来自于历届真题&#xff0c;去重、合并后&#xff0c;每道题都有参考答案和解析。 为帮助孩子自测和练习&…

演示:WPF开发的Diagram自动化流程图应用

一、目的&#xff1a;演示Diaram应用功能 二、预览 三、功能列表 功能模块 通用测试 流程图 仪器仪表 机器人 网络通信测试 PLC测试 轮毂生产线流程测试 图像处理 目标检测 绘图 思维导图 图表 流程图功能 模板管理 工程管理 模块许可管理 工具栏 开始 停止 删除 清除 …

RabbitMQ实践——对不可路由的消息的处理方法

大纲 无备用&#xff08;Alternate&#xff09;交换器构建交换器、队列和绑定关系测试代码抛弃不可路由消息返还不可路由消息 有备用&#xff08;Alternate&#xff09;交换器创建带备用&#xff08;Alternate&#xff09;交换器的交换器mandatory非mandatory 总结 在实际工作中…

【DevOps】Elasticsearch 数据跨集群同步方案

目录 1、Elasticsearch Cross-Cluster Replication (CCR) 1.1、优点 1.2、缺点 1.3、步骤 1.4、示例 2. Logstash 或其他 ETL 工具 2.1、优点 2.2、缺点 2.3、步骤 3. Apache Kafka 或 RabbitMQ 3.1、优点 3.2、缺点 3.3、步骤 4、使用 Reindex API 进行跨集群同…

【LeetCode最详尽解答】42-接雨水 Trapping-Rain-Water

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家&#xff01; 链接: 42-接雨水 直觉 通过可视化图形来解决这个问题会更容易理解和解决。 给定输入: height [0,1,…

mediasoup源码分析--channel创建及信令交互

mediasoup源码分析--channel创建及信令交互 概述跨职能图业务流程图代码剖析 概述 在golang实现mediasoup的tcp服务及channel通道一文中&#xff0c;已经介绍过信令服务中tcp和channel的创建&#xff0c;本文主要讲解c中mediasoup的channel创建&#xff0c;以及信令服务和medi…

基于CentOS的全新Linux机器安装Jenkins并生成Allure报告

目录 一、安装Docker 二、安装Docker Compose 三、准备测试用例 四、配置docker-compose.yml 五、启动Jenkins 六、配置Jenkins和Allure插件 七、创建含pytest的Jenkins任务 一、安装Docker 在CentOS上&#xff0c;首先更新包管理工具并安装所需的包。 sudo yum update…

12.3 Go 测试覆盖率

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

基于Elementui组件,在vue中实现多种省市区前端静态JSON数据展示并支持与后端交互功能,提供后端名称label和id

基于Elementui组件&#xff0c;在vue中实现多种省市区前端静态数据&#xff08;本地JSON数据&#xff09;展示并支持与后端交互功能&#xff0c;提供后端名称label和id 话不多说&#xff0c;先上图 1.支持传递给后端选中省市区的id和名称&#xff0c;示例非常完整&#xff0c…

阿里云 邮件系统DNS域名解析 搭配 postfix+dovecot 邮件服务器

1 创建邮箱域名A记录(一般邮箱客户端&#xff0c;增加pop,imap,stmp 3条记录) 登录阿里云控制台--云解析DNS 2 MX记录 3 SPF记录

【论文复现|智能算法改进】基于多策略的改进蜜獾算法及其应用

目录 1.算法原理2.改进点3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】蜜獾算法&#xff08;HBA&#xff09;原理及实现 2.改进点 限制反向学习机制 在挖掘模式和蜂蜜模式不同路径更新的基础上引入限制反向学习机制&#xff0c;在算法迭代时&#xff0c;对当前的…

Fegin如何传参form-data文件

Form-data传输file参数&#xff0c;这个大家都比较清楚&#xff0c;那么针对于Fegin参数file参数该如何操作呢&#xff01;下面截图来找到对应的参数关系。 一、之前我们在postMan中是这种传参的&#xff0c;那么如果使用Feigin来传输文件File 二、在Fegin中传form-data参数&a…

C/C++ struct stat介绍

目录 前言 struct stat struct stat 使用 参考 共勉 前言 本文详细介绍了stat结构体的成员变量&#xff0c;以及使用案例&#xff0c;希望能够帮到您。 struct stat struct stat 结构体用于表示文件或者文件系统对象信息的一种结构体的声明&#xff0c;通常在POSIX&#x…

Mac M3 Pro 部署Flink-1.16.3

目录 1、下载安装包 2、解压及配置 3、启动&测试 4、测试FlinkSQL读取hive数据 以上是mac硬件配置 1、下载安装包 官网&#xff1a;Downloads | Apache Flink 网盘&#xff1a; Flink 安装包 https://pan.baidu.com/s/1IN62_T5JUrnYUycYMwsQqQ?pwdgk4e Flink 已…