从响应式编程到 Combine 实践

本文介绍了响应式编程的概念,重点探讨了Apple的Combine框架,包括其优势、基本概念如Publisher、Subscriber,以及在Resso中的实践应用。结合具体的代码示例,阐述了如何使用Combine简化异步事件处理,特别是在处理多个网络请求时的优雅解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大约一年前,Resso 接入了 Combine,利用响应式编程简化了代码逻辑,也积累了很多实践经验。本文会从响应式编程的基本思想并逐步深入介绍 Combine 的概念与最佳实践, 希望能帮助更多的同学顺利上手并实践响应式编程,少踩坑。

等等,Resso 是什么?Resso 来源于 Resonate(共鸣),是字节跳动推出的一个社交音乐流媒体平台,专为下一代音乐发烧友设计,使他们能够通过对音乐的热爱来表达和与他人建立联系。

书回正文,所谓的响应式编程到底是什么呢?

熟悉 Combine 的同学可以直接跳到实践建议部分。​

响应式编程

维基百科对响应式编程的定义是:

  • 在计算中,响应式编程是一种面向数据流和变化传播的声明式编程范式。

虽然定义中每个字都认识,但连起来却十分费解。我们可以把定义中的内容分开来理解,逐个击破。首先,让我们来看下声明式编程。

声明式编程

声明式和指令式编程是常见的编程范式。在指令式编程中,开发者通过组合运算、循环、条件等语句让计算机执行程序。声明式与指令式正相反,如果说指令式像是告诉计算机 How to do,而声明式则是告诉计算机 What to do。其实大家都接触过声明式编程,但在编码时并不会意识到。各类 DSL 和函数式编程都属于声明式编程的范畴。

举个例子,假设我们想要获取一个整形数组里的所有奇数。按照指令式的逻辑,我们需要把过程拆解为一步一步的语句:

  • 遍历数组中的所有元素。
  • 判断是否为奇数。
  • 如果是的话,加入到结果中。继续遍历。
var results = [Int]()
for num in values {
    if num %2 != 0 {
        results.append(num)
    }
}

如果按声明式编程来,我们的想法可能是“过滤出所有奇数”,对应的代码就十分直观:

var results = values.filter { $0 % 2 != 0 }

可见上述两种编程方式有着明显的区别:

  • 指令式编程:描述过程(How),计算机直接执行并得结果。
  • 声明式编程:描述结果(What),让计算机为我们组织出具体过程,最后得到被描述的结果。

“面向数据流和变化传播”

用说人话的方式解释,面向数据流和变化传播是响应未来发生的事件流。

  1. 事件发布:某个操作发布了事件A​,事件A​ 可以携带一个可选的数据B 。
  2. 操作变形:事件A​ 与数据B​ 经过一个或多个的操作发生了变化,最终得到事件A'​ 与数据B'。
  3. 订阅使用:在消费端,有一个或多个订阅者来消费处理后的A'​ 和B',并进一步驱动程序其他部分 (如 UI )

在这个流程中,无数的事件组成了事件流,订阅者不断接受到新的事件并作出响应。

至此,我们对响应式编程的定义有了初步的理解,即以声明的方式响应未来发生的事件流。在实际编码中,很多优秀的三方库对这套机制进一步抽象,为开发者提供了功能各异的接口。在 iOS 开发中,有三种主流的响应式“流派“。

响应式流派

  • ReactiveX:RxSwift
  • Reactive Streams:Combine
  • Reactive*:ReactiveCocoa / ReactiveSwift /ReactiveObjc

这三个流派分别是 ReactiveX、Reactive Streams 和 Reactive*。ReactiveX 接下来会详细介绍。Reactive Stream 旨在定义一套非阻塞式异步事件流处理标准,Combine 选择了它作为实现的规范。以 ReactiveCocoa 为代表的 Reactive* 在 Objective-C 时代曾非常流行,但随着 Swift 崛起,更多开发者选择了 RxSwift 或 Combine,导致 Reactive* 整体热度下降不少。

ReactiveX (Reactive Extension)

ReactiveX 最初是微软在 .NET 上实现的一个响应式的拓展。它的接口命名并不直观,如 Observable (可观测的) 和 Observer(观测者)。ReactiveX 的优势在于创新地融入了许多函数式编程的概念,使得整个事件流的变形非常灵活。这个易用且强大的概念迅速被各个语言的开发者青睐,因此 ReactiveX 在很多语言都有对应版本的实现(如 RxJS,RxJava,RxSwift),都非常流行。Resso 的 Android 团队就在重度使用 RxJava。

为何选择 Combine

Combine 是 Apple 在 2019 年推出的一个类似 RxSwift 的异步事件处理框架。

通过对事件处理的操作进行组合 (combine) ,来对异步事件进行自定义处理 (这也正是 Combine 框架的名字的由来)。Combine 提供了一组声明式的 Swift API,来处理随时间变化的值。这些值可以代表用户界面的事件,网络的响应,计划好的事件,或者很多其他类型的异步数据。

Resso iOS 团队也曾短暂尝试过 RxSwift,但在仔细考察 Combine 后,发现 Combine 无论是在性能、调试便捷程度上都优于 RxSwift,此外还有内置框架和 SwiftUI 官配的特殊优势,受其多方面优势的吸引,我们全面切换到了 Combine。

Combine 的优势

相较于 RxSwift,Combine 有很多优势:

  • Apple 出品
  • 内置在系统中,对 App 包体积无影响
  • 性能更好
  • Debug 更便捷
  • SwiftUI 官配

性能优势

Combine 的各项操作相较 RxSwift 有 30% 多的性能提升。

Reference: Combine vs. RxSwift Performance Benchmark Test Suite

Debug 优势

由于 Combine 是一方库,在 Xcode 中开启了 Show stack frames without debug symbols and between libraries 选项后,无效的堆栈可以大幅的减少,提升了 Debug 效率。

// 在 GlobalQueue 中接受并答应出数组中的值
[1, 2, 3, 4].publi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值