Swift Combine — Subject Publishers(PassthroughSubject CurrentValueSubject)

news2024/12/23 17:36:22

本文主要介绍一下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 in
        switch completion {
          case .finished:
            print("---> Finished")
          case .failure(let error):
            print("---> Error: \(error.localizedDescription)")
        }
      } receiveValue: { value in
        print("---> 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 in
        switch completion {
          case .finished:
            print("---> Finished")
          case .failure(let error):
            print("---> Error: \(error.localizedDescription)")
        }
      } receiveValue: { value in
        print("---> 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 in
        switch completion {
          case .finished:
            print("---> Finished")
          case .failure(let error):
            print("---> Error: \(error.localizedDescription)")
        }
      } receiveValue: { value in
        print("---> 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.coloradmin.cn/o/1847491.html

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

相关文章

基于jeecgboot-vue3的Flowable流程-自定义业务表单处理(一)支持同一个业务多个关联流程的选择支持

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 这部分先讲讲支持自定义业务表单一个业务服务表单多个流程的支持处理 1、后端mapper部分 如下&#xff0c;修改selectSysCustomFormByServiceName为list对象&#xff0c;以便支持多个 &…

苹果手机短信删除了怎么恢复?有那些方法?

IPhone短信删除怎么恢复&#xff1f;现在大多数人都会使用社交软件沟通交流&#xff0c;短信的用武之地已经没以前那么多&#xff0c;但是它的重要性一点都不能忽视&#xff0c;有些重要的短信内容值得我们保留&#xff0c;如果不小心删除了这些短信内容该怎么恢复&#xff1f;…

全网首测!文生软件平台码上飞CodeFlying,效果炸裂!

前言&#xff1a; 提到AIGC&#xff0c;在大家的印象中应该就是让AI自己生成文字&#xff0c;图片等内容吧。随着今年Sora&#xff0c;Suno的爆火&#xff0c;将AIGC的应用场景又拉到了一个新的高度&#xff0c;为人们带来了更多的遐想。在未来&#xff0c;或许可以用AI来生成…

【LLM-多模态】高效多模态大型语言模型综述

一、结论写在前面 模型规模的庞大及训练和推理成本的高昂&#xff0c;限制了MLLMs在学术界和工业界的广泛应用。因此&#xff0c;研究高效轻量级的MLLMs具有巨大潜力&#xff0c;特别是在边缘计算场景中。 论文深入探讨了高效MLLM文献的领域&#xff0c;提供了一个全面的视角…

简易人工智能入门

一、监督or非监督 监督学习&#xff08;Supervised Learning&#xff09;&#xff1a;训练集有标记信息&#xff08;Y&#xff09;&#xff0c;学习方式有分类和回归 无监督学习&#xff08;Unsupervised Learning&#xff09;&#xff1a;训练集没有标记信息&#xff0c;学习…

20240621将需要自启动的部分放到RK3588平台的Buildroot系统的rcS文件中

20240621将需要自启动的部分放到RK3588平台的Buildroot系统的rcS文件中 2024/6/21 17:15 开发板&#xff1a;飞凌OK3588-C SDK&#xff1a;Rockchip原厂的Buildroot 缘起&#xff1a;在凌OK3588-C的LINUX R4系统启动的时候&#xff0c;需要拉高GPIO4_B5、GPIO3_B7和GPIO3_D0。…

高通Android 12 aapt报错问题踩坑

背景 最近因为要做多module模块&#xff0c;出现aapt报错&#xff0c;于是简单记录下&#xff0c;踩坑过程。 1、我一开始项目中三个module&#xff0c;然后在build.gradle设置androidApplication plugins {alias(libs.plugins.androidApplication) }2、运行完之后都是报下面…

中服云产品远程运维系统

中服云产品远程运维系统主要针对设备售后市场服务的管理&#xff0c;利用工业物联网技术&#xff0c;一方面面向设备生产厂商&#xff0c;将分散的经销商、客户、销售出去的设备统一管理&#xff1b;另一方面面向设备使用厂家&#xff0c;实现设备实时运行监控&#xff1b;系统…

五种实用方法!手把手教你系统盘瘦身

随着电脑的使用时间变长&#xff0c;电脑硬盘会逐渐被各种类型的数据占满&#xff0c;其中系统盘的可用空间也在慢慢变小。这是因为系统在运行过程中会产生大量临时文件和缓存文件&#xff0c;同时&#xff0c;系统的每一次更新升级也都会生成相关的文件夹存放在系统盘中&#…

C语言:生命周期和作用域,static和extern

关键字static与extern 1.作用域&#xff08;scope&#xff09;&#xff1a;代码中能够访问到变量的范围&#xff08;变量可以被使用的文本区间&#xff09;。&#xff08;分为全局作用域和局部作用域&#xff09; ☺全局作用域&#xff1a;在整个程序中都能访问的变量。通常…

机器学习算法的电影推荐系统以及票房预测系统

一、实验概述 1. 实验目标 本项目希望基于电影数据集&#xff0c;依据电影的简介、关键词、预算、票房、用户评分等特征来对电影进行分析&#xff0c;并完成以下任务&#xff1a; 对电影特征的可视化分析对电影票房的预测多功能个性化的电影推荐算法 2. 数据集 针对票房预…

58-DOS与DDOS分析(正常TCP会话与SYN Flood攻击、ICMP Flood 攻击、SNMP放大攻击等)

目录 正常 TCP 会话与 SYN Flood 攻击 1、正常的三次握手过程&#xff1a; 2、 SYN Flood 攻击 一、攻击windows系统&#xff1a; 二、攻击web网站 &#xff1a; 拒绝服务攻击工具-Hping3-Syn Flood 攻击 拒绝服务攻击工具--Hping3--ICMP Flood 攻击 sockstress攻击 So…

Studying-代码随想录训练营day16| 513找到左下角的值、112.路径总和、106从中序与后序遍历序列构造二叉树

第十六天&#xff0c;二叉树part03&#x1f4aa;&#x1f4aa;&#x1f4aa;&#xff0c;编程语言&#xff1a;C 目录 513找到左下角的值 112.路径总和 113.路径总和II 106从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树 总结 513找到左下角的值…

【计算机毕业设计】​206校园顺路代送微信小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

思聪私生女能继位吗?王健林表态,家族不会亏待

黄一鸣坚称&#xff1a;这绝对是王思聪的骨肉&#xff01;常言道&#xff0c;常在河边走&#xff0c;哪能不湿鞋。换女友如换装的王思聪&#xff0c;这次终于跌入了陷阱&#xff01;他的网红女友们如繁星点点&#xff0c;但选择标准始终如一——年轻、美丽。在金钱上&#xff0…

Nodejs 第七十九章(Kafka进阶)

kafka前置知识在上一章讲过了 不再复述 kafka进阶 1. server.properties配置文件 server.properties是Kafka服务器的配置文件&#xff0c;它用于配置Kafka服务的各个方面&#xff0c;包括网络设置、日志存储、消息保留策略、安全认证 #broker的全局唯一编号&#xff0c;不能…

市场价格到底是因为什么而变动?

在外汇及广泛的金融市场中&#xff0c;影响金融工具价格起伏的因素纷繁复杂。然而&#xff0c;万变不离其宗&#xff0c;无论是哪个市场&#xff0c;价格的最终决定力量始终是供需之间的平衡法则。 对于外汇、大宗商品等金融市场而言&#xff0c;表面上似乎受宏观经济数据、央…

极速查询:StarRocks 存算分离 Compaction 原理 调优指南

作者&#xff1a;丁凯&#xff0c;StarRocks TSC member/镜舟科技云原生技术负责人 StarRocks 在数据摄入过程中&#xff0c;每次操作都会创建一个新的数据版本。在查询时&#xff0c;为了得到准确的结果&#xff0c;必须将所有版本合并。然而&#xff0c;随着历史数据版本的累…

Midjourney v6 快速入门指南

Midjourney V6快速入门教程来了&#xff0c;这是Midjourney的AI图像生成器的又一次令人印象深刻的升级。最显著的是&#xff0c;V6在逼真渲染和图像中的文字功能方面取得了重大进展。 在这篇文章中&#xff0c;我们将探讨如何开始使用Midjourney V6&#xff0c;并提供一些示例…

【单片机毕业设计选题24018】-基于STM32和阿里云的农业大棚系统

系统功能: 系统分为手动和自动模式&#xff0c;上电默认为自动模式&#xff0c;自动模式下系统根据采集到的传感器值 自动控制&#xff0c;温度过低后自动开启加热&#xff0c;湿度过高后自动开启通风&#xff0c;光照过低后自动开启补 光&#xff0c;水位过低后自动开启水泵…