iOS 中的Combine 框架简介

Combine 是 Apple 在 WWDC 2019 推出的 响应式编程框架 ,用于在 iOS/macOS/watchOS/tvOS 上处理异步事件流(如网络请求、用户输入、定时器等)。它使用 声明式代码风格,用 Publisher 和 Subscriber 的方式来"组合"异步数据流,从而替代传统的回调、Notification、KVO 等机制。


🧠 一句话理解 Combine

Combine 就是 Apple 官方推出的"响应式数据流处理工具",使用它可以优雅地处理异步逻辑。


🧩 Combine 的核心概念

名称 说明
Publisher 发布者,表示"可以发出值"的对象(如网络请求、Notification)
Subscriber 订阅者,订阅发布者的值并响应处理(如 UI 更新、状态更新)
Operator 操作符,用于转换或组合数据流(如 map, filter, merge)
Subject 特殊的 Publisher,也能作为数据源主动"发送值"
Cancellable 返回值,可用于取消订阅(防止内存泄漏)

🔨 基本使用示例

1️⃣ 创建 Publisher

csharp 复制代码
let justPublisher = Just("Hello Combine") // 发出一个值后就完成

2️⃣ 订阅 Publisher

bash 复制代码
justPublisher.sink { value in
    print("接收到值:(value)")
}

🔁 常用操作符(Operators)

操作符 说明
map 映射值
filter 过滤值
combineLatest 合并多个 Publisher
flatMap 链式转换并展开 Publisher
debounce 防抖处理,如输入框
removeDuplicates 去重处理
catch 错误捕获并恢复

示例:

bash 复制代码
let numbers = [1, 2, 3, 4, 5].publisher

numbers
    .map { $0 * 2 }
    .filter { $0 > 5 }
    .sink { print("结果:($0)") }

💡 Subject 的使用

PassthroughSubject:用于外部"主动"发送值

dart 复制代码
let subject = PassthroughSubject<String, Never>()

subject
    .sink { print("接收:($0)") }

subject.send("Hello")
subject.send("World")

CurrentValueSubject:有初始值,并能追踪最新状态

bash 复制代码
let current = CurrentValueSubject<Int, Never>(0)

current
    .sink { print("当前值:($0)") }

current.send(10)

🧩 网络请求示例

php 复制代码
import Combine
import Foundation

struct Post: Decodable {
    let title: String
}

var cancellables = Set<AnyCancellable>()

URLSession.shared.dataTaskPublisher(for: URL(string: "https://jsonplaceholder.typicode.com/posts/1")!)
    .map(.data)
    .decode(type: Post.self, decoder: JSONDecoder())
    .sink(receiveCompletion: { completion in
        print("完成:(completion)")
    }, receiveValue: { post in
        print("标题:(post.title)")
    })
    .store(in: &cancellables)

🧯 如何取消订阅(防止内存泄漏)

scss 复制代码
let cancellable = Just("Hello").sink { print($0) }
cancellable.cancel()

使用 .store(in: &cancellables) 自动释放:

scss 复制代码
var cancellables = Set<AnyCancellable>()

Just("Hello")
    .sink { print($0) }
    .store(in: &cancellables)

🧠 Combine 与 UIKit 结合示例

监听UITextField输入变化

swift 复制代码
import Combine
import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var textField: UITextField!
    var cancellables = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: textField)
            .compactMap { ($0.object as? UITextField)?.text }
            .debounce(for: .milliseconds(300), scheduler: RunLoop.main)
            .sink { text in
                print("输入:(text)")
            }
            .store(in: &cancellables)
    }
}

🆚 与 RxSwift 区别

项目 Combine RxSwift
是否官方 ✅ Apple 官方 ❌ 三方库(强大但外部)
支持平台 iOS 13+ iOS 9+
学习曲线 相对较陡 相对陡(语法更复杂)
文档与社区 官方文档丰富 社区丰富

✅ Combine 使用建议

  • iOS 13+ 原生项目推荐使用 Combine;
  • UI 绑定推荐使用 @Published + ObservableObject;
  • 更复杂的流处理可以结合 Subject 和 Operator;
  • 异步任务建议统一封装成 Publisher 进行管理。
相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端