Combine的介绍与使用

目录

  • 一、Combine 框架介绍
  • 二、核心概念
  • 三、基础使用示例
    • 3.1、创建 Publisher & 订阅
    • 3.2、操作符链式调用
    • 3.3、Subject 使用(手动发送值)
    • 3.4、网络请求处理
    • 3.5、组合多个 Publisher
    • 3.6、错误处理
  • 四、核心操作符速查表 Operator
  • 五、UIKit 绑定示例
  • 六、SwiftUI 集成示例
  • 七、最佳实践建议

一、Combine 框架介绍

Combine 是 Apple 在 2019 年推出的声明式响应式编程框架,专为 Swift 设计,深度集成在 Apple 生态系统中(iOS 13+,macOS 10.15+)。它提供了一套统一的 API 来处理随时间变化的数据流,特别适合处理异步事件、数据绑定和复杂的状态管理。

二、核心概念

  1. Publisher:数据生产者(发布事件)
  2. Subscriber:数据消费者(接收事件)
  3. Operator:数据转换操作符
  4. Subject:可手动发送值的特殊 Publisher
  5. Scheduler:线程调度管理器

三、基础使用示例

3.1、创建 Publisher & 订阅

import Combinevar cancellables = Set<AnyCancellable>()// 创建 Publisher
let stringPublisher = Just("Hello Combine!") // 发送单个值
let arrayPublisher = [1, 2, 3].publisher    // 发送序列值// 订阅 Publisher
stringPublisher.sink(receiveCompletion: { completion inswitch completion {case .finished: print("Completed")case .failure(let error): print("Error: \(error)")}},receiveValue: { value inprint(value) // "Hello Combine!"}).store(in: &cancellables) // 存储订阅

3.2、操作符链式调用

[1, 2, 3, 4, 5].publisher.filter { $0 % 2 == 0 }     // 过滤偶数.map { $0 * 10 }            // 转换值.sink { print($0) }         // 接收值.store(in: &cancellables)/* 输出:
20
40
*/

3.3、Subject 使用(手动发送值)

// PassthroughSubject:不保存当前值
let passSubject = PassthroughSubject<String, Never>()// CurrentValueSubject:保存当前值
let currentSubject = CurrentValueSubject<Int, Never>(0)// 订阅
passSubject.sink { print("收到: \($0)") }.store(in: &cancellables)// 发送值
passSubject.send("第一次发送")
passSubject.send("第二次发送")// 修改当前值
currentSubject.value = 5
currentSubject.send(10) // 发送新值

3.4、网络请求处理

struct User: Decodable {let name: String
}func fetchUser() -> AnyPublisher<User, Error> {let url = URL(string: "https://api.example.com/user")!return URLSession.shared.dataTaskPublisher(for: url).map(\.data) // 提取数据.decode(type: User.self, decoder: JSONDecoder()) // 解码.receive(on: DispatchQueue.main) // 切换到主线程.eraseToAnyPublisher() // 类型擦除
}// 使用
fetchUser().sink(receiveCompletion: { print($0) },receiveValue: { user inprint("用户名: \(user.name)")}).store(in: &cancellables)

3.5、组合多个 Publisher

let usernamePublisher = PassthroughSubject<String, Never>()
let passwordPublisher = PassthroughSubject<String, Never>()// 组合最新值
Publishers.CombineLatest(usernamePublisher, passwordPublisher).map { username, password in!username.isEmpty && password.count >= 6}.sink { isValid inprint("表单有效? \(isValid)")}.store(in: &cancellables)// 触发验证
usernamePublisher.send("user")
passwordPublisher.send("123")   // 输出: false
passwordPublisher.send("123456") // 输出: true

3.6、错误处理

enum CustomError: Error { case test }Fail(error: CustomError.test) // 立即发送错误的Publisher.catch { error -> Just<String> inprint("捕获错误: \(error)")return Just("默认值")}.sink(receiveValue: { print($0) }).store(in: &cancellables)/* 输出:
捕获错误: test
默认值
*/

四、核心操作符速查表 Operator

操作符功能描述
map值转换
filter条件过滤
flatMap展平嵌套Publisher
combineLatest组合多个Publisher的最新值
merge合并多个Publisher
debounce防抖动(用于搜索输入)
throttle节流(控制事件频率)
retry失败重试
switchToLatest切换到最新Publisher

五、UIKit 绑定示例

class ViewController: UIViewController {@IBOutlet weak var textField: UITextField!@IBOutlet weak var label: UILabel!private var cancellables = Set<AnyCancellable>()override func viewDidLoad() {super.viewDidLoad()// 创建文本框内容Publisherlet textPublisher = NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: textField).compactMap { ($0.object as? UITextField)?.text }// 绑定到标签textPublisher.filter { $0.count > 3 }.map { "输入: \($0)" }.assign(to: \.text, on: label).store(in: &cancellables)}
}

六、SwiftUI 集成示例

import SwiftUI
import Combinestruct ContentView: View {@StateObject private var viewModel = ViewModel()var body: some View {VStack {TextField("搜索", text: $viewModel.searchText)List(viewModel.results, id: \.self) { item inText(item)}}}
}class ViewModel: ObservableObject {@Published var searchText = ""@Published var results: [String] = []private var cancellables = Set<AnyCancellable>()init() {$searchText.debounce(for: .seconds(0.5), scheduler: RunLoop.main).removeDuplicates().flatMap { query -> AnyPublisher<[String], Never> inself.search(query: query)}.assign(to: \.results, on: self).store(in: &cancellables)}func search(query: String) -> AnyPublisher<[String], Never> {// 模拟网络请求let results = query.isEmpty ? [] : ["\(query)结果1", "\(query)结果2"]return Just(results).eraseToAnyPublisher()}
}

七、最佳实践建议

  1. 内存管理:始终使用 store(in: &cancellables) 管理订阅生命周期
  2. 线程切换:使用 receive(on:) 确保在正确线程更新 UI
  3. 错误处理:合理使用 catch, retry 等操作符
  4. 避免强引用:使用 [weak self] 防止循环引用
  5. 调试技巧:使用 print() 操作符跟踪事件流

注意:Combine 要求最低系统版本 iOS 13+/macOS 10.15+。对于支持旧系统的项目,可考虑使用 RxSwift 或其他响应式框架。

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

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

相关文章

【Java笔记】七大排序

目录1. 直接插入排序2. 希尔排序3. 选择排序4. 堆排序(重要)5. 冒泡排序6. 快速排序&#xff08;重要&#xff09;6.1 Hoare 法6.1.1 Hoare 法优化6.2 挖坑法&#xff08;重点&#xff09;6.3 快速排序的非递归写法7. 归并排序海量数据的排序问题8. 总结1. 直接插入排序 时间复…

H.264编解码(NAL)

在我们的日常生活中&#xff0c;比如有缓存电影或者是发送视频的需求。如果没有视频压缩&#xff0c;一部手机只能存几分钟视频&#xff0c;1TB 硬盘也装不下几部电影&#xff0c;用 4G 网络发一段 1 分钟视频&#xff0c;可能需要几十分钟&#xff08;甚至传不完&#xff09;&…

新手向:Python自动化办公批量重命名与整理文件系统

本文将详细介绍如何使用Python实现一个强大的文件批量重命名与整理工具&#xff0c;帮助开发者自动化这一繁琐过程。本教程面向Python初学者&#xff0c;通过一个完整的项目案例&#xff0c;讲解文件系统操作的核心技术。我们将构建的工具将具备以下功能&#xff1a;基于正则表…

C++ 左值右值、左值引用右值引用、integral_constant、integral_constant的元模板使用案例

C 左值右值、左值引用右值引用、integral_constant、integral_constant的元模板使用案例一、左值右值1.左值2.右值二、左值引用右值引用1.左值引用2.右值引用总结三、integral_constant四、integral_constant的元模板使用案例1.求最大整数2.内存对齐alignof关键字元模板计算内存…

c++算法一

1.双指针总结&#xff1a;1.复写0这道题&#xff0c;告诉我们要正难其反&#xff0c;我们从后向前进行重写&#xff0c;删除某些数字的时候&#xff0c;我们可以从前向后遍历&#xff0c;但是增加一些数字的时候会对后面的数据进行覆盖&#xff0c;所以要从后向前进行2.快乐数涉…

LeetCode-283. 移动零(Java)

283. 移动零 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: n…

【数据库】慢SQL优化 - MYSQL

一、数据库故障的关键点 引起数据库故障的因素有操作系统层面、存储层面&#xff0c;还有断电断网的基础环境层面&#xff08;以下称为外部因素&#xff09;&#xff0c;以及应用程序操作数据库和人为操作数据库这两个层面&#xff08;以下称内部因素&#xff09;。这些故障中外…

桶排序算法深度剖析

&#x1f50d; 桶排序算法深度剖析 &#x1f3af; 核心原理图解⚙️ 完整算法流程 #mermaid-svg-LyB6SpaZ132X4Wtn {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-LyB6SpaZ132X4Wtn .error-icon{fill:#552222;}#mer…

对S32K144做的BMS安装快速开发Simulink库及BMS例程介绍

前言 本章介绍BMS硬件功能及SimuLink库为主&#xff0c;捎带介绍一些例程内容 注意&#xff1a;例程所用的协议均是自定义的 自做的SimuLink库也会不定期更新 BMS例程的内容不定期维护添加 当前的BMS没有主动均衡功能&#xff0c;这个有考虑后期加上&#xff0c;当前还处于…

urlencode、html实体编码、unicode

目录 urlencode html实体编码 Unicode编码 urlencode URL编码也称为百分号编码&#xff0c;用于将URL中的特殊字符转换为安全传输的格式。英文数字一般不编码 特点&#xff1a; 使用%后跟两个十六进制数字表示字符 空格编码为或%20 保留字符&#xff08;; / ? : & …

【HarmonyOS】元服务概念详解

【HarmonyOS】元服务概念详解 最近几年&#xff0c;我们手里的设备越来越多——手机、平板、手表、车机……光是管理这些设备上的APP就够头疼了&#xff1a;下载要流量、安装占内存、换个设备又得重新弄一遍。有没有更简单的方式&#xff1f;HarmonyOS推出的“元服务”&#xf…

vscode/cursor怎么自定义文字、行高、颜色

JetBrains Mono: A free and open source typeface for developers | JetBrains: Developer Tools for Professionals and Teams 首先下载上面的文字&#xff0c;然后右键全选&#xff0c;安装 然后重启cursor 下载插件Apc Customize UI 点击设置 把下面的代码复制进去&…

JavaScript 与 C语言基础知识差别

一&#xff0c; 变量声明对比 C语言&#xff1a; int age 20; // 必须指定类型 float price 9.99; char grade A; const double PI 3.14; // 常量JavaScript&#xff1a; let age 20; // 数字 var price 9.99; // 现在不用&#xff0c;有缺点 co…

无缝矩阵支持音频分离带画面分割功能的全面解析

一、技术原理与实现方式1. 音频分离技术核心功能&#xff1a;HDMI无缝矩阵通过硬件或软件实现音频加嵌与分离功能&#xff0c;支持多设备音频的独立处理与增强。实现方式&#xff1a;音频加嵌&#xff1a;将外部音频信号&#xff08;如麦克风、调音台&#xff09;嵌入HDMI信号中…

AI创作系列第18篇:海狸IM移动端UI统一大升级 - 从混乱到规范的技术重构之路

AI创作系列第18篇&#xff1a;海狸IM移动端UI统一大升级 - 从混乱到规范的技术重构之路本文是海狸IM AI创作系列的第18篇文章&#xff0c;记录7月11日-13日周末期间对移动端的UI统一升级工作。这次重构不是功能性的&#xff0c;而是架构性的 - 我们重新设计了整个UI架构&#x…

八、nginx搭建,实现vue跳转nginx跳转gateway

基本的调用链路: vue调用nginx,nginx反向代理gateway,gateway看用户是否登录,没有登录的话,就创建验证码并先输入密码后获取token。 截止现在我们创建了两个项目能够通过feign调用,并且创建好了gateway,且能调用对应的项目。 这一章节,我们搭建好nginx,通过反向代理,…

C++ 中常见的字符串定义方式及其用法

引言 最近在学习C&#xff0c;下面将从基础到进阶的顺序&#xff0c;列出一些 C 中常见的字符串定义方式及其用法&#xff0c;包含完整代码和详细注释&#xff0c;加深对代码的理解。 C 风格字符串&#xff08;char*或 char[]&#xff09; 定义方式 #include <iostream>i…

下一代防火墙-防范DOS攻击、IPS防护、web防护实验

一、实验拓扑二、实验设备1.山石网科系列下一代防火墙2.三层交换机一台3.windows两台4.各种工具&#xff0c;如hyenae、小旋风服务器、永恒之蓝等等三、实验目的1.掌握网络攻击防护策略配置2.通过下一代防火墙来防护服务器免受DOS攻击四、防范Dos攻击实验1.将一台windows配置为…

【人工智能】通过 Dify 构建智能助手

通过 Dify 构建智能助手1.定义2.如何使用智能助手3.添加助手需要的工具4.配置 Agent5.配置对话开场白6.添加文件上传7.调试与预览8.应用发布1.定义 智能助手&#xff08;Agent Assistant&#xff09;&#xff0c;利用大语言模型的推理能力&#xff0c;能够自主对复杂的人类任务…

破局与重构:文心大模型开源的产业变革密码

——从技术垄断到生态共享的战略转型深度解析 引言&#xff1a;一场静悄悄的革命 2024年&#xff0c;当百度宣布文心大模型4.5系列全面开源时&#xff0c;这不仅仅是一次技术发布&#xff0c;更是一场关于AI产业未来走向的战略博弈。在全球AI竞争白热化的当下&#xff0c;开源意…