iOS Swift-Combine

Combine学习链接

Swift Combine 框架是 Apple 于 2019 年在 WWDC 上发布的,旨在简化响应式编程。响应式编程是一种编程范式,专注于处理异步事件流,例如用户输入、网络请求或文件变化等。Combine 框架的主要目标是通过统一和简化事件处理逻辑,减少传统回调或通知机制的复杂性。

Combine 框架的核心思想是将数据变化表示为“发布者”(Publisher),它可以发出值、完成事件或者错误事件。订阅者(Subscriber)则会订阅这些发布者,以响应数据的变化。Combine 的发布-订阅模式与其他响应式编程库(例如 RxSwift)类似,但它与 Swift 和 Apple 的生态系统高度集成,专门为 iOS、macOS、watchOS 和 tvOS 量身定制。

Combine 的出现解决了开发者在处理异步任务时可能遇到的挑战,使得代码更加简洁、易读和易于维护,同时提供了对 Swift 语言类型系统的强大支持。

核心概念

在 Combine 框架中,处理响应式编程的核心是四个基本概念:Publisher、Subscriber、Subscription 和 Subject。这些概念共同构建了数据流的架构,允许我们在异步事件发生时响应和处理数据。下面详细解释每个概念:

1. Publisher(发布者)

它定义了一个数据源,可以发出值、完成事件或错误。Publisher 会持续向它的订阅者发出这些事件。Publisher 可以发出三种类型的事件:

  • 值(Value): 发布的数据。
  • 完成(Completion): 事件完成,发布者不会再发出任何事件。
  • 错误(Failure): 出现错误,发布者停止发送事件,并向订阅者发送错误。

常见的内置 Publisher 类型:

  • Just: 只发布一个值,然后立即完成。
  • Empty: 不发出任何值,只发送完成或错误事件。
  • Future: 异步产生一个值,并且只发送一次值或错误。
  • PassthroughSubject: 允许外部手动发布值,不保留历史值。
  • CurrentValueSubject: 发布当前值,并对新订阅者发送最新的值。
  • Deferred: 延迟创建 Publisher,直到有订阅者时才执行。
  • Fail: 立即发送错误并完成,用于模拟失败。
  • Timer.TimerPublisher: 定期发送时间值,用于计时或轮询。
  • NotificationCenter.Publisher: 发布通知中心的通知。
  • URLSession.DataTaskPublisher: 处理网络请求,发送响应数据或错误。
截屏2024-11-26 17.33.59.png
2. Subscriber(订阅者)

Subscriber 是 Publisher 的消费者。它接收来自 Publisher 发出的数据或事件,并做出相应处理。订阅者通过订阅(subscribe)特定的 Publisher 来监听它发出的值或状态变化。

Subscriber 的关键在于它的两个方法:

  • receive(_ input: Input): 接收发出的值。
  • receive(completion: Subscribers.Completion<Failure>): 接收完成或错误事件。
    Combine 提供了 sinkassign 等方便的方法来创建订阅者。
截屏2024-11-26 17.34.05.png
3. Subscription(订阅)

Subscription 是 Subscriber 和 Publisher 之间的桥梁。它管理数据流的生命周期,控制订阅者从发布者接收多少数据。它本质上代表了一个订阅操作。

当订阅者开始监听一个 Publisher 时,Publisher 会创建一个 Subscription,并将它传递给订阅者。Subscriber 可以通过 Subscription 控制是否需要取消订阅或者请求更多数据(例如在背压机制中应用)。

截屏2024-11-26 17.34.13.png
4. Subject(主题)

Subject 是 Combine 框架中特殊类型的 Publisher,它既可以是 Publisher,也可以是 Subscriber。它允许你手动发布值给订阅者,非常适合用于桥接外部事件或多次触发的值。

Combine 中有两种常见的 Subject:

  • PassthroughSubject: 不保存任何值,直接将接收到的值发布给订阅者。
  • CurrentValueSubject: 保存最后发布的一个值,新订阅者会首先接收到当前值。
    使用场景:

如果你想手动触发某些值或事件,可以使用 Subject。
当你想让多个订阅者订阅并立即收到当前最新值时,可以使用 CurrentValueSubject

截屏2024-11-26 17.34.21.png

操作符 Operators

在 Swift 的 Combine 框架中,Operators(操作符) 是用于对数据流进行处理、转换、过滤等操作的核心组件。操作符可以对从发布者(Publisher)发出的值进行链式处理,类似于函数式编程中的 map、filter 等操作。通过使用操作符,开发者可以灵活地对事件流进行操作,以满足各种需求。

Combine 中的操作符为响应式编程提供了非常强大的数据处理能力。通过这些操作符,开发者可以轻松地处理和转换异步事件流,从而减少代码复杂性并提高代码的可维护性。

以下是 Combine 中常用的一些操作符:

1. Transforming Operators(转换操作符)
  • map:将发布者发出的值进行映射,转换成另一个类型的值。
截屏2024-11-26 17.34.29.png
  • compactMap:类似于 map,但可以过滤掉 nil 值,只返回非空值。
截屏2024-11-26 17.34.35.png
  • flatMap:用于将每个元素映射到一个新的发布者,然后将这些发布者的元素合并成一个新的发布者。
截屏2024-11-26 17.34.44.png
2. Filtering Operators(过滤操作符)
  • filter:只通过满足条件的值,过滤掉不符合条件的元素。
截屏2024-11-26 17.34.51.png
  • removeDuplicates:移除连续重复的值。
截屏2024-11-26 17.34.56.png
3. Combining Operators(组合操作符)
  • merge:将两个或多个发布者的输出合并成一个流。
截屏2024-11-26 17.35.11.png
  • combineLatest:当两个或多个发布者都发出值时,组合它们的最新值。
截屏2024-11-26 17.35.23.png
  • zip:与 combineLatest 类似,但它只会在两个发布者都有值时才会发出值,并且会按照顺序组合。
截屏2024-11-26 17.35.32.png
4. Timing Operators(时间操作符)
  • debounce:延迟发出值,直到指定时间段内没有新的值发出。
截屏2024-11-26 17.35.41.png
  • delay:延迟发布者的输出。
截屏2024-11-26 17.35.49.png
5. Error Handling Operators(错误处理操作符)
  • catch:处理发布者在发出错误时,返回一个新的发布者。
截屏2024-11-26 17.35.58.png
  • retry:如果发布者遇到错误,可以重新尝试订阅指定次数。
截屏2024-11-26 17.36.04.png
6. Reducing Operators(归约操作符)
  • reduce:累积值,直到发布者完成并发出最终结果。
截屏2024-11-26 17.36.13.png
  • scan:类似于 reduce,但会在每个新值到达时发出中间结果。
截屏2024-11-26 17.36.23.png

高阶 - Scheduler

Scheduler 控制代码执行上下文,决定数据流中发布者和订阅者的运行线程。它是 Combine 中多线程和任务调度的核心,允许指定代码在主线程、后台线程或自定义队列中执行。常见应用:后台网络请求、复杂计算、延迟任务和轻量级频繁任务处理。合理使用 Scheduler 可优化程序性能和用户体验。

Scheduler 的作用
  • 线程管理:Scheduler 主要用于控制异步操作在哪个线程执行,特别是在涉及网络请求、文件 I/O 或耗时操作时,确保它们不会阻塞主线程,从而影响 UI 响应。

  • 任务调度:通过 Scheduler,可以安排任务的执行顺序,例如:在后台执行复杂操作并在操作完成后切换回主线程更新 UI。

  • 频率控制:使用 Scheduler 可以指定执行频率,如在延迟、间隔时间或某个特定的时间后执行任务。
    Combine 框架通过使用 subscribe(on:)receive(on:) 来指定发布者和订阅者的执行上下文。

  • subscribe(on:):用于指定数据发布的上下文,控制数据是在哪个 Scheduler(线程)上产生的。

  • receive(on:):用于指定数据接收的上下文,控制 Subscriber 接收数据并处理它时在哪个 Scheduler 上运行,常用于将操作结果传回主线程。

典型的 Scheduler 类型

Combine 中的 Scheduler 主要分为几种类型,常用于处理不同场景的调度需求:

  • DispatchQueue: 最常用的调度器,允许你在主线程或后台线程上执行任务。
  • RunLoop: 主要用于事件驱动的循环,适用于任务调度频繁但任务执行轻量的场景。
  • OperationQueue: 用于管理基于队列的任务执行顺序和优先级。
  • ImmediateScheduler: 在当前线程上立即执行任务。

典型的应用场景

1. 在后台线程执行网络请求,主线程更新 UI

在 UI 应用中,通常需要在后台执行耗时任务(如网络请求或数据库操作),然后在主线程更新 UI。可以通过 subscribe(on:) 切换到后台线程,处理数据后通过 receive(on:) 切换到主线程更新 UI。

截屏2024-11-26 17.37.01.png
2. 延迟任务执行

有时候需要让某些任务延迟执行或在特定时间间隔执行。可以通过 DispatchQueue 调度任务执行。

截屏2024-11-26 17.37.06.png
3. 频繁计算任务调度

对于一些频繁且高优先级的任务,比如基于用户输入的实时计算(如实时搜索),可以通过 RunLoop 来执行调度,因为 RunLoop 对于高频率的轻量任务处理效率较高。

截屏2024-11-26 17.37.13.png
4. 避免主线程阻塞

在执行复杂的计算任务时,使用 subscribe(on:) 将计算操作移至后台,避免阻塞主线程,确保 UI 的流畅性。

截屏2024-11-26 17.37.21.png

总结

Swift Combine 是 Apple 在 2019 年推出的响应式编程框架,旨在简化异步事件流的处理。Combine 中的核心概念有四个,分别是 发布数据或事件的源头 Publisher、接收来自 Publisher 的数据或事件 的 Subscriber、管理 Publisher 和 Subscriber 之间的关系 的 Subscription 、用于桥接外部数据源并手动控制数据流的 Subject。

除了4个基本概念,还有一些很实用的操作符:

  • 转换操作符:如 map、compactMap
  • 过滤操作符:如 filter、removeDuplicates
  • 组合操作符:如 merge、combineLatest、zip
  • 时间操作符:如 debounce、delay
  • 错误处理操作符:如 catch、retry
  • 归约操作符:如 reduce、scan

Combine 框架通过提供统一的事件处理方式,简化了异步编程,提高了代码的可读性和可维护性。它与 Swift 和 Apple 生态系统高度集成,为 iOS、macOS、watchOS 和 tvOS 开发提供了强大的响应式编程工具。

Publisher: 发布者是一个对象,它可以发出一系列的事件,比如值、错误或完成信号;
Subscriber: 订阅者是一个对象,它可以订阅一个或多个发布者,并对发布者发出的事件做出响应;

Operators(操作符):Combine 提供了许多操作符,可以用于转换、组合和处理发布者发出的事件。例如,map 用于映射值,filter 用于过滤事件,merge 用于合并多个发布者的事件等。

Cancellable(可取消):订阅一个发布者会返回一个 Cancellable 对象,你可以使用这个对象来取消订阅,释放资源;

Subject(主题):主题是 Combine 中的一种特殊类型的发布者,既可以发送值也可以接收值。有 PassthroughSubject 和 CurrentValueSubject 等类型;

Schedulers(调度器):Combine 使用调度器来确定在哪个线程上执行操作。有一些内置的调度器,比如 DispatchQueue.main 和 DispatchQueue.global();

下面是一个简单的例子,演示了 Combine 中的一些概念:

截屏2024-11-26 17.38.11.png

学习Demo:

Combine Demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • Swift Combine 框架是 Apple 于 2019 年在 WWDC 上发布的,旨在简化响应式编程。响应式...
    wflx阅读 166评论 0 2
  • Swift中的Combine是一种用于处理异步事件流的框架,它提供了一种声明式、函数式的编程方式,可以让开发者更加...
    anny_4243阅读 5,477评论 0 3
  • Combine 是 Swift 中的一个框架,用于处理和组合异步和事件驱动的操作。要快速理解 Combine,可以...
    大成小栈阅读 1,125评论 1 4
  • 简介 Combine是Apple在2019年WWDC上推出的一个新框架。该框架提供了一个声明性的Swift API...
    云天涯丶阅读 24,450评论 5 22
  • 什么是Combine “一套统一的声明性API,用于处理随时间变化的值,其有着支持泛型,类型安全,组成优先,请求驱...
    猴子的饼干阅读 9,008评论 3 17