swift-Combine 学习笔记1
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 可以发出三种类型的事件:
常见的内置 Publisher 类型:
2. Subscriber(订阅者)
Subscriber 是 Publisher 的消费者。它接收来自 Publisher 发出的数据或事件,并做出相应处理。订阅者通过订阅(subscribe)特定的 Publisher 来监听它发出的值或状态变化。
Subscriber 的关键在于它的两个方法:
Combine 提供了 sink 和 assign 等方便的方法来创建订阅者。
3. Subscription(订阅)
Subscription 是 Subscriber 和 Publisher 之间的桥梁。它管理数据流的生命周期,控制订阅者从发布者接收多少数据。它本质上代表了一个订阅操作。
当订阅者开始监听一个 Publisher 时,Publisher 会创建一个 Subscription,并将它传递给订阅者。Subscriber 可以通过 Subscription 控制是否需要取消订阅或者请求更多数据(例如在背压机制中应用)。
4. Subject(主题)
Subject 是 Combine 框架中特殊类型的 Publisher,它既可以是 Publisher,也可以是 Subscriber。它允许你手动发布值给订阅者,非常适合用于桥接外部事件或多次触发的值。
Combine 中有两种常见的 Subject:
使用场景:
操作符 Operators
在 Swift 的 Combine 框架中,Operators(操作符) 是用于对数据流进行处理、转换、过滤等操作的核心组件。操作符可以对从发布者(Publisher)发出的值进行链式处理,类似于函数式编程中的 map、filter 等操作。通过使用操作符,开发者可以灵活地对事件流进行操作,以满足各种需求。
Combine 中的操作符为响应式编程提供了非常强大的数据处理能力。通过这些操作符,开发者可以轻松地处理和转换异步事件流,从而减少代码复杂性并提高代码的可维护性。
以下是 Combine 中常用的一些操作符:
1. Transforming Operators(转换操作符)
2. Filtering Operators(过滤操作符)
3. Combining Operators(组合操作符)
4. Timing Operators(时间操作符)
5. Error Handling Operators(错误处理操作符)
6. Reducing Operators(归约操作符)
高阶 - Scheduler
Scheduler 控制代码执行上下文,决定数据流中发布者和订阅者的运行线程。它是 Combine 中多线程和任务调度的核心,允许指定代码在主线程、后台线程或自定义队列中执行。常见应用:后台网络请求、复杂计算、延迟任务和轻量级频繁任务处理。合理使用 Scheduler 可优化程序性能和用户体验。
Scheduler 的作用
Combine 框架通过使用 subscribe(on:) 和 receive(on:) 来指定发布者和订阅者的执行上下文。
典型的 Scheduler 类型
Combine 中的 Scheduler 主要分为几种类型,常用于处理不同场景的调度需求:
典型的应用场景
1. 在后台线程执行网络请求,主线程更新 UI
在 UI 应用中,通常需要在后台执行耗时任务(如网络请求或数据库操作),然后在主线程更新 UI。可以通过 subscribe(on:) 切换到后台线程,处理数据后通过 receive(on:) 切换到主线程更新 UI。
2. 延迟任务执行
有时候需要让某些任务延迟执行或在特定时间间隔执行。可以通过 DispatchQueue 调度任务执行。
3. 频繁计算任务调度
对于一些频繁且高优先级的任务,比如基于用户输入的实时计算(如实时搜索),可以通过 RunLoop 来执行调度,因为 RunLoop 对于高频率的轻量任务处理效率较高。
4. 避免主线程阻塞
在执行复杂的计算任务时,使用 subscribe(on:) 将计算操作移至后台,避免阻塞主线程,确保 UI 的流畅性。