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 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有个初步的了解和使用,文中如果有不对的地方,还望大家指正。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

豆浆机水位传感器工作原理

豆浆机水位传感器的工作原理基于光电效应&#xff0c;利用近红外发光二极管和光敏接收器的组合实现液位的精确检测与控制。在豆浆机内部&#xff0c;传感器安装在水箱底部或需要检测液位的位置&#xff0c;起到监测和控制豆浆机水位的重要作用。 传感器包括一个近红外发光二极…

Suno新技能亮相:完美复刻歌手音色,我甚至不敢公开!

之前写过一篇文章 颠覆音乐创作! Suno史诗级更新&#xff0c;随便哼哼就能出一首好听的歌曲&#xff1f; Suno支持上传一段音频或者自己的哼唱进行续创歌曲&#xff0c;这个功能大家有玩出花样嘛&#xff1f; 可能很多人&#xff0c;还不知道这个到底有啥用! 大家先看看这首《满…

如何用Vue3和p5.js绘制交互式3D饼图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于p5.js实现色彩轮和饼状图的动态可视化 应用场景 本代码利用p5.js库&#xff0c;创建了一个交互式的色彩轮和饼状图可视化界面。它适用于需要展示颜色信息或数据分布情况的场景&#xff0c;如设计、数据分…

docker通过容器id查看运行命令;Portainer监控管理docker容器

1、docker通过容器id查看运行命令 参考&#xff1a;https://blog.csdn.net/a772304419/article/details/138732138 docker inspect 运行镜像id“Cmd”: [ “–model”, “/qwen-7b”, “–port”, “10860”, “–max-model-len”, “4096”, “–trust-remote-code”, “–t…

【招联消费金融股份】有限公司2024年5月18日【算法开发岗暑期实习】一面试经验分享

招联消费金融股份有限公司2024年5月18日面试经验分享 面试流程&#xff1a;共30多分钟&#xff0c;先3分钟自我介绍&#xff0c;然后细细介绍简历上面的论文和实习信息。问题1&#xff1a;扩散模型的noise schedule有什么研究。问题2&#xff1a;有哪些常见的数学分布问题3&…

jquery动态效果插件之ScrollMagic

ScrollMagic 是一个强大的 JavaScript 库,可以帮助开发者在页面滚动时触发各种动画效果。它支持复杂的滚动交互,非常适合制作富交互的网页。 这里他使用了ScrollMagic的几种滚动效果: 视差滚动效果:页面上的一些元素在滚动时会产生视差滚动效果,即元素以不同的速度移动,营造出…

MES管理系统中的质量管理活动是什么

在制造业的广阔天地中&#xff0c;质量管理如同航船的指南针&#xff0c;指引着产品品质的航行方向。而随着科技的日新月异&#xff0c;MES管理系统在质量管理领域扮演着越来越重要的角色。MES管理系统不仅连接了企业的管理层与车间生产现场&#xff0c;更在质量管理的各个环节…

洗地机性价比高的是哪一款?行内人告诉你

在浏览前&#xff0c;希望您轻触屏幕上方的“关注”按钮&#xff0c;让我后续为您带来更多实用且精彩的内容&#xff0c;感谢您的支持&#xff01; 洗地机作为现在的流行清洁工具&#xff0c;它的魅力之处在于&#xff1a;性价比极高&#xff0c;大多数家庭无需花费过多就能把…

语义分割和目标检测的关系

目录 1.语义分割的目标 2.目标检测的目标 3.两种任务的异同之处 从大方向的任务特点上来说 &#xff08;1&#xff09;物体的位置 &#xff08;2&#xff09;物体的分类 从数据格式来说 (1&#xff09;语义分割的数据格式 (2&#xff09;目标检测的数据格式 1.语义分…

Java面试题之MySQL事务详解

事务是什么 MySQL中的事务&#xff08;Transaction&#xff09;是数据库管理系统执行的一个逻辑操作单元&#xff0c;它是由一系列数据库操作组成的逻辑工作单元。事务是并发控制的单位&#xff0c;也是用户定义的一个操作序列。事务的主要目的是确保数据的完整性和一致性&…

Trying to access array offset on value of type null

主要原因是版本7.4以后PHP解析器会对null类型的下标访问直接报错 背景&#xff1a; laravel框架 同时使用了扩展A和扩展B 扩展A要求 php>7.4,同时扩展B的对null类型的下标访问不兼容php7.4 修改扩展B不太现实&#xff0c;毕竟扩展B中有太多的对null类型的下标访问。 解决…

SQL Server中CROSS APPLY连接操作

在 SQL Server 中&#xff0c;CROSS APPLY 是一个连接操作&#xff0c;它类似于 INNER JOIN&#xff0c;但有一些关键差异&#xff0c;特别是在处理表值函数&#xff08;TVF&#xff09;、行集函数或子查询时。CROSS APPLY 返回对于外部查询中的每一行&#xff0c;在内部查询或…

osi七层网络模型安全加固

应用层加固 应用层的攻击&#xff1a; 1、针对应用层协议的攻击&#xff1a;HTTP攻击、DNS攻击、电子邮件攻击等&#xff0c;利用应用层协议的漏洞&#xff0c;构造恶意数据包&#xff0c;是目标服务器执行恶意代码或暴露敏感信息 HTTP攻击&#xff1a;XSS、CSRF、HTTP头注入…

如何让AI 帮你生成 git 提交信息

在协同开发的项目中&#xff0c;我们肯定避免不了使用git提交代码&#xff0c;所以经常会看到了一些描述不清的提交信息。当遇到种情况时&#xff0c;我们也不必为此责怪开发人员&#xff0c;因为我们确实很难记住你在 git 提交时刚刚做了什么。 Nutlope / aicommits 一个使用 …

高速公路视频监控系统与车牌抓拍:EasyCVR视频监控技术助力交通道路安全监控

随着科技的不断发展&#xff0c;高速公路视频监控与车牌抓拍系统作为智能交通的重要组成部分&#xff0c;日益发挥着不可或缺的作用。这些先进的技术不仅提高了道路交通的管理效率&#xff0c;也为保障行车安全提供了新的手段。 高速公路视频监控系统的应用&#xff0c;极大地…

Spring-事件

Java 事件/监听器编程模型 设计模式-观察者模式的拓展 可观察者对象(消息发送者) Java.util.Observalbe观察者 java.util.Observer 标准化接口(标记接口) 事件对象 java.util.EventObject事件监听器 java.util.EventListener public class ObserverDemo {public static vo…

如何在招聘中开始使用AI?

在人工智能时代&#xff0c;招聘团队面临着“用更少的钱做更多的事情”的压力&#xff1a;用更少的钱和更少的团队。根据一项调查&#xff0c;58%的受访者认为&#xff0c;“提高我们助教团队的效率&#xff0c;降低成本”是明年招聘职位的首要任务。在招聘中使用人工智能是提高…

40、基于深度学习的线性预测设计(matlab)

1、原理及流程 深度学习的线性预测是一种利用深度神经网络模型进行线性回归预测的方法。其设计原理主要基于神经网络的层次化特性&#xff0c;利用多层感知器&#xff08;MLP&#xff09;等模型进行特征学习和非线性变换&#xff0c;从而提高线性预测的准确性。 设计流程如下…

▶《强化学习的数学原理》(2024春)_西湖大学赵世钰 Ch0 一张图讲完强化学习原理

PPT 截取有用信息。 课程网站做习题。总体 MOOC 过一遍 1、视频 学堂在线 习题 2、相应章节 过电子书 [2023.8 版本] 复习 3、总体 MOOC 过一遍 学堂在线 课程页面链接 中国大学MOOC 课程页面链接 B 站 视频链接 PPT和书籍下载网址&#xff1a; 【github链接】 onedrive链接&…

原子阿波罗STM32F767程序的控制器改为STM32F407驱动LCD屏

由于手里没有原子大神的F429开发板&#xff0c;又还想学习原子大神的F429开发板程序&#xff0c;前几天&#xff0c;经过更换控制器&#xff0c;成功把原子大神的F429开发板程序用到了F407开发板上&#xff0c;驱动LCD屏显示成功&#xff0c;目的&#xff0c;就是熟悉原子大神的…