当前位置: 首页 > news >正文

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.lryc.cn/news/587755.html

相关文章:

  • C++-linux 7.文件IO(三)文件元数据与 C 标准库文件操作
  • SVD、DCT图像压缩实践
  • 什么是电磁锁控制板?24路锁控板的使用步骤概述
  • MySQL数据库的基础操作
  • Java Integer包装类缓存机制详解
  • 《汇编语言:基于X86处理器》第7章 复习题和练习,编程练习
  • 最大最小公平策略(Max-Min Fairness)
  • 测试驱动开发(TDD)实战:在 Spring 框架实现中践行 “红 - 绿 - 重构“ 循环
  • 软考 系统架构设计师系列知识点之杂项集萃(111)
  • EasyExcel实现Excel文件导入导出
  • 文心4.5开源之路:引领技术开放新时代!
  • Cannot add property 0, object is not extensible
  • 收集飞花令碎片——VS调试技巧
  • Linux(Ubuntu)硬盘使用情况解析(已房子举例)
  • 中间件部署
  • Ubuntu22.04 python环境管理
  • LabVIEW-Origin 船模数据处理系统
  • ubuntu之坑(十五)——设备树
  • SnapKit介绍与使用
  • EPLAN 电气制图(八):宏应用与变频器控制回路绘制全攻略
  • 基于esp32系列的开源无线dap-link项目使用介绍
  • RocketMQ 5.x初体验
  • Linux 音频的基石: ALSA
  • React 第六十九节 Router中renderMatches的使用详解及注意事项
  • Android 性能优化:启动优化全解析
  • 019_工具集成与外部API调用
  • LabVIEW浏览器ActiveX事件交互
  • SpringMVC1
  • 数字孪生技术引领UI前端设计新潮流:智能交互界面的个性化定制
  • 【Linux系统】进程切换 | 进程调度——O(1)调度队列