📋 目录
一、ReactiveCocoa框架使用详解
1. ReactiveCocoa框架概述
ReactiveCocoa(简称 RAC)是一个基于 ReactiveSwift 的响应式编程框架,用于处理异步事件流和状态管理。它是 GitHub 开源的项目,提供了声明式的 API 来处理时间序列数据。
1.1 什么是ReactiveCocoa
ReactiveCocoa 是一个函数式响应式编程(FRP)框架,允许你通过组合不同的操作符来处理异步事件序列。它提供了声明式的 API 来处理时间序列数据。
核心特点:
- 函数式响应式编程:基于函数式编程和响应式编程的结合
- 类型安全:充分利用 Swift 的类型系统
- 状态管理:提供 Property 和 MutableProperty 管理状态
- Action模式:提供 Action 处理用户交互
- UIKit集成:深度集成 UIKit 控件
1.2 ReactiveCocoa vs RxSwift vs Combine
| 特性 | ReactiveCocoa | RxSwift | Combine |
|---|---|---|---|
| 平台 | iOS、macOS | 跨平台 | Apple 生态(iOS 13+) |
| 语言 | Swift | Swift | Swift |
| 官方支持 | ❌ GitHub 开源 | ❌ 第三方 | ✅ Apple 官方 |
| 核心类型 | Signal、SignalProducer | Observable | Publisher |
| 状态管理 | Property、MutableProperty | BehaviorSubject | @Published |
| Action模式 | ✅ Action | ❌ | ❌ |
| 学习曲线 | 陡峭 | 陡峭 | 中等 |
| 生态 | ReactiveSwift、ReactiveObjC | RxCocoa | SwiftUI |
1.3 ReactiveCocoa生态系统
- ReactiveSwift:核心框架,提供 Signal、SignalProducer 等
- ReactiveCocoa:UIKit/AppKit 集成,提供控件绑定
- ReactiveObjC:Objective-C 版本
1.4 安装方式
CocoaPods:
pod 'ReactiveSwift', '~> 7.0'
pod 'ReactiveCocoa', '~> 12.0'
SPM:
dependencies: [
.package(url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", from: "7.0.0"),
.package(url: "https://github.com/ReactiveCocoa/ReactiveCocoa.git", from: "12.0.0")
]
1.5 编程思想(背后的范式与理念)
ReactiveCocoa 明确标榜函数式响应式编程(FRP),将函数式与响应式结合;理解其背后的编程思想,能更好地区分 Signal / SignalProducer、Property、Action 的适用场景。
(1)函数式响应式编程(FRP)
- 核心:在「响应式」的事件流之上,用函数式的方式组合与变换——把「随时间发生的事件」视为可映射、可过滤、可合并的值,通过纯函数组合成新流,而不是在观察者闭包里写满副作用。
- 在 RAC 中:
Signal/SignalProducer表示事件流,map、filter、flatMap等操作符对流做纯变换,observe或start才真正消费并产生副作用;流与副作用边界清晰。 - 与「仅响应式」的对比:FRP 强调「流即数据」,用转换与组合表达业务逻辑,观察者只做「最后一步」的响应,便于测试和复用。
(2)声明式 vs 命令式
| 维度 | 命令式(Imperative) | 声明式(Declarative) |
|---|---|---|
| 关注点 | 「怎么做」:显式顺序与分支 | 「做什么」:描述数据/事件如何变换与约束 |
| 典型写法 | 回调嵌套、状态变量、if-else | 链式操作符:map / filter / combineLatest |
| 在 RAC 中 | 手写「请求 → 回调里判断 → 再请求」 | 用 signal.map(...).flatMap(...).observeValues(...) 描述整条流水线 |
声明式让「事件从哪来、如何变换、到哪去」一目了然,便于阅读和单元测试。
(3)函数式思想(组合与不可变)
- 组合(Composition):每个操作符只做一件事,通过
.map().filter().flatMap(.latest)等组合成完整逻辑;小能力组合成大能力,避免巨型闭包。 - 不可变(Immutability):操作符不修改原 Signal/SignalProducer,而是返回新的;原流不变,便于复用和推理。
- 副作用边界:纯变换放在操作符链中,副作用(UI 更新、写库、弹窗)集中在
observeValues/startWithValues或Action的 execution 中,便于测试和并发安全。
(4)流与时间(Streams & Time)
- 把所有「会随时间产生的事件」都视为时间序列:value、value、…、completed/failed/interrupted。
- RAC 区分热信号(Signal)与冷信号(SignalProducer):热信号有订阅即开始发送、多订阅者共享同一时间线;冷信号每次 start 才执行、每次订阅独立。时间相关操作符如
debounce、throttle表达「何时」而不只是「何值」。
(5)观察者与「推」「拉」
- 观察者模式:Observer 通过
observe订阅 Signal,或通过start启动 SignalProducer,在事件发生时被通知。 - 推模型:Signal 是「推」——事件由发送端推动,观察者被动接收;SignalProducer 是「按需拉」——只有
start时才创建并执行,适合表示「一次异步操作」或「延迟计算」。
(6)Action 与「意图-执行」分离
- 思想:用户操作(点击、下拉)是意图,网络请求、校验、弹窗是执行;将「意图」与「执行」分离,便于禁用、重试、统一错误处理。
- 在 RAC 中:
Action接收输入(如按钮 tap 或输入值),内部用 SignalProducer 描述一次执行,输出与错误统一由Action暴露;UI 只绑定「能否执行」与「执行结果」,不写一堆isLoading、error状态。
小结:ReactiveCocoa 用声明式的事件流(Signal/SignalProducer)和可组合的操作符,在函数式响应式的范式下做异步与事件处理;用 Property 管理可变状态、用 Action 封装「意图-执行」,并用 Scheduler 控制线程。掌握这些思想后,再区分「用 Signal 还是 SignalProducer」「何时用 Property、何时用 Action」会更自然。
2. 核心概念
2.1 Signal(信号)
Signal 是 ReactiveCocoa 的核心类型,表示一个可以观察的事件流。
protocol SignalProtocol {
associatedtype Value
associatedtype Error: Swift.Error
func observe(_ observer: Observer<Value, Error>) -> Disposable?
}
特点:
- 可以发出零个或多个值
- 可能以完成或错误结束
- 是引用类型(class)
- 热信号(Hot Signal):有订阅者时立即开始发送事件
事件类型:
enum Event<Value, Error: Swift.Error> {
case value(Value) // 值事件
case failed(Error) // 错误事件
case completed // 完成事件
case interrupted // 中断事件
}
示例:
let (signal, observer) = Signal<String, Never>.pipe()
signal.observeValues { value in
print("收到值: \(value)")
}
observer.send(value: "Hello")
observer.send(value: "World")
observer.sendCompleted()
2.2 SignalProducer(信号生产者)
SignalProducer 是延迟创建 Signal 的类型,类似于 RxSwift 的 Observable。
struct SignalProducer<Value, Error: Swift.Error> {
private let startHandler: (Observer<Value, Error>, Lifetime) -> Void
func start(_ observer: Observer<Value, Error>) -> Disposable
}
特点:
- 冷信号(Cold Signal):只有在被订阅时才开始发送事件
- 每次订阅都会创建新的 Signal
- 适合表示异步操作
示例:
let producer = SignalProducer<String, Never> { observer, lifetime in
observer.send(value: "Hello")
observer.send(value: "World")
observer.sendCompleted()
}
producer.startWithValues { value in
print("收到值: \(value)")
}
2.3 Observer(观察者)
Observer 是接收 Signal 事件的类型。
final class Observer<Value, Error: Swift.Error> {
func send(value: Value)
func send(error: Error)
func sendCompleted()
func sendInterrupted()
}
示例:
let (signal, observer) = Signal<Int, Never>.pipe()
signal.observe { event in
switch event {
case .value(let value):
print("值: \(value)")
case .completed:
print("完成")
case .failed(let error):
print("错误: \(error)")
case .interrupted:
print("中断")
}
}
observer.send(value: 1)
observer.send(value: 2)
observer.sendCompleted()
2.4 Disposable(可释放资源)
Disposable 表示订阅关系,用于取消订阅和释放资源。
protocol Disposable {
func dispose()
}
CompositeDisposable:
let disposable = CompositeDisposable()
disposable += signal.observeValues { value in
print(value)
}
disposable += anotherSignal.observeValues { value in
print(value)
}
// 释放所有订阅
disposable.dispose()
3. Signal与SignalProducer
3.1 Signal创建方式
pipe
创建 Signal 和 Observer。
let (signal, observer) = Signal<String, Never>.pipe()
signal.observeValues { print($0) }
observer.send(value: "Hello")
never
创建永不发出事件的 Signal。
let signal = Signal<Int, Never>.never()
signal.observeValues { print($0) } // 永远不会执行
empty
创建立即完成的 Signal。
let signal = Signal<Int, Never>.empty()
signal.observeCompleted { print("完成") }
failed
创建立即失败的 Signal。
enum MyError: Error {
case failure
}
let signal = Signal<Int, MyError>.failed(.failure)
signal.observeFailed { print("错误: \($0)") }
3.2 SignalProducer创建方式
init
使用闭包创建 SignalProducer。
let producer = SignalProducer<String, Never> { observer, lifetime in
observer.send(value: "A")
observer.send(value: "B")
observer.sendCompleted()
}
producer.startWithValues { print($0) }
value
创建发出单个值的 SignalProducer。
let producer = SignalProducer<String, Never>(value: "Hello")
producer.startWithValues { print($0) }
values
从序列创建 SignalProducer。
let producer = SignalProducer<String, Never>(values: ["A", "B", "C"])
producer.startWithValues { print($0) }
error
创建立即失败的 SignalProducer。
let producer = SignalProducer<Int, MyError>(error: .failure)
producer.startWithFailed { print("错误: \($0)") }
empty
创建立即完成的 SignalProducer。
let producer = SignalProducer<Int, Never>.empty
producer.startWithCompleted { print("完成") }
never
创建永不发出事件的 SignalProducer。
let producer = SignalProducer<Int, Never>.never
producer.startWithValues { print($0) } // 永远不会执行
3.3 Signal vs SignalProducer
Signal(热信号):
- 立即开始发送事件
- 多个观察者共享同一个事件流
- 适合表示已经发生的事件
SignalProducer(冷信号):
- 延迟创建,只有在订阅时才开始
- 每个观察者获得独立的事件流
- 适合表示异步操作
转换:
// SignalProducer -> Signal
let producer = SignalProducer<String, Never>(value: "Hello")
let signal = producer.promoteToSignal()
// Signal -> SignalProducer
let (signal, observer) = Signal<String, Never>.pipe()
let producer = SignalProducer(signal)
4. Property与MutableProperty
4.1 Property
Property 是不可变的状态容器,表示一个随时间变化的值。
protocol PropertyProtocol {
associatedtype Value
var value: Value { get }
var signal: Signal<Value, Never> { get }
var producer: SignalProducer<Value, Never> { get }
}
特点:
- 只读属性
- 提供当前值
- 提供 Signal 和 SignalProducer 观察变化
示例:
let property = Property(value: "初始值")
// 获取当前值
print(property.value) // 输出: 初始值
// 观察变化
property.signal.observeValues { value in
print("值变化: \(value)")
}
4.2 MutableProperty
MutableProperty 是可变的状态容器。
final class MutableProperty<Value>: MutablePropertyProtocol {
var value: Value { get set }
var signal: Signal<Value, Never> { get }
var producer: SignalProducer<Value, Never> { get }
init(_ value: Value)
}
特点:
- 可读写属性
- 修改值时会发出事件
- 新观察者会立即收到当前值
示例:
let property = MutableProperty("初始值")
// 观察变化
property.signal.observeValues { value in
print("值变化: \(value)")
}
// 立即输出: 值变化: 初始值
// 修改值
property.value = "新值" // 输出: 值变化: 新值
property.value = "另一个值" // 输出: 值变化: 另一个值
4.3 Property绑定
双向绑定:
let property1 = MutableProperty("")
let property2 = MutableProperty("")
// 双向绑定
property1 <~ property2
property2 <~ property1
property1.value = "Hello" // property2.value 也变为 "Hello"
property2.value = "World" // property1.value 也变为 "World"
单向绑定:
let source = MutableProperty("源")
let target = MutableProperty("目标")
// 单向绑定:source -> target
target <~ source
source.value = "新值" // target.value 也变为 "新值"
target.value = "修改" // source.value 不变
5. Action
Action 是 ReactiveCocoa 特有的类型,用于处理用户交互和异步操作。
5.1 Action基本使用
let action = Action<String, String, Never> { input in
return SignalProducer { observer, lifetime in
// 执行异步操作
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
observer.send(value: "结果: \(input)")
observer.sendCompleted()
}
}
}
// 执行 Action
action.apply("输入").startWithValues { result in
print(result) // 输出: 结果: 输入
}
5.2 Action状态
Action 提供多个状态 Signal:
let action = Action<String, String, Never> { input in
return SignalProducer(value: "结果: \(input)")
}
// 观察执行状态
action.isExecuting.signal.observeValues { isExecuting in
print("执行中: \(isExecuting)")
}
// 观察值
action.values.observeValues { value in
print("值: \(value)")
}
// 观察错误
action.errors.observeValues { error in
print("错误: \(error)")
}
// 执行
action.apply("输入").start()
5.3 Action与UIButton绑定
let action = Action<Void, String, Never> {
return SignalProducer(value: "按钮点击")
}
// 绑定到按钮
button.reactive.pressed = CocoaAction(action) { _ in }
// 观察结果
action.values.observeValues { result in
print(result)
}
6. Operators操作符
6.1 转换操作符
map
转换每个值。
SignalProducer(values: [1, 2, 3])
.map { $0 * 2 }
.startWithValues { print($0) }
// 输出: 2, 4, 6
flatMap
将 Signal 发出的值转换为 SignalProducer,然后合并。
SignalProducer(values: ["A", "B", "C"])
.flatMap(.latest) { letter in
SignalProducer(values: [1, 2]).map { "\(letter)\($0)" }
}
.startWithValues { print($0) }
// 输出: A1, A2, B1, B2, C1, C2
scan
累积值。
SignalProducer(values: [1, 2, 3, 4, 5])
.scan(0, +)
.startWithValues { print($0) }
// 输出: 1, 3, 6, 10, 15
6.2 过滤操作符
filter
过滤值。
SignalProducer(values: [1, 2, 3, 4, 5])
.filter { $0 % 2 == 0 }
.startWithValues { print($0) }
// 输出: 2, 4
skip
跳过前几个值。
SignalProducer(values: [1, 2, 3, 4, 5])
.skip(first: 2)
.startWithValues { print($0) }
// 输出: 3, 4, 5
take
获取前几个值。
SignalProducer(values: [1, 2, 3, 4, 5])
.take(first: 3)
.startWithValues { print($0) }
// 输出: 1, 2, 3
distinctUntilChanged
移除连续重复的值。
SignalProducer(values: [1, 1, 2, 2, 3, 3])
.distinctUntilChanged()
.startWithValues { print($0) }
// 输出: 1, 2, 3
6.3 组合操作符
combineLatest
组合多个 Signal 的最新值。
let (signal1, observer1) = Signal<String, Never>.pipe()
let (signal2, observer2) = Signal<Int, Never>.pipe()
signal1.combineLatest(with: signal2)
.observeValues { value1, value2 in
print("\(value1): \(value2)")
}
observer1.send(value: "A") // 无输出(等待 signal2)
observer2.send(value: 1) // 输出: A: 1
observer1.send(value: "B") // 输出: B: 1
observer2.send(value: 2) // 输出: B: 2
merge
合并多个 Signal。
let (signal1, observer1) = Signal<Int, Never>.pipe()
let (signal2, observer2) = Signal<Int, Never>.pipe()
signal1.merge(with: signal2)
.observeValues { print($0) }
observer1.send(value: 1) // 输出: 1
observer2.send(value: 2) // 输出: 2
observer1.send(value: 3) // 输出: 3
zip
按顺序组合多个 Signal。
let (signal1, observer1) = Signal<String, Never>.pipe()
let (signal2, observer2) = Signal<Int, Never>.pipe()
signal1.zip(with: signal2)
.observeValues { value1, value2 in
print("\(value1): \(value2)")
}
observer1.send(value: "A") // 等待 signal2
observer1.send(value: "B") // 等待 signal2
observer2.send(value: 1) // 输出: A: 1
observer2.send(value: 2) // 输出: B: 2
6.4 时间操作符
debounce
防抖,等待指定时间后发出最新值。
let (signal, observer) = Signal<String, Never>.pipe()
signal.debounce(0.5, on: QueueScheduler.main)
.observeValues { print($0) }
observer.send(value: "H") // 不输出
observer.send(value: "He") // 不输出
observer.send(value: "Hel") // 不输出
observer.send(value: "Hell") // 不输出
observer.send(value: "Hello") // 0.5秒后输出: Hello
throttle
节流,在指定时间间隔内只发出第一个值。
let (signal, observer) = Signal<String, Never>.pipe()
signal.throttle(1.0, on: QueueScheduler.main)
.observeValues { print($0) }
observer.send(value: "A") // 立即输出: A
observer.send(value: "B") // 不输出(1秒内)
observer.send(value: "C") // 不输出(1秒内)
// 1秒后
observer.send(value: "D") // 输出: D
delay
延迟发出值。
SignalProducer(values: [1, 2, 3])
.delay(1.0, on: QueueScheduler.main)
.startWithValues { print($0) }
// 1秒后依次输出: 1, 2, 3
7. Schedulers调度器
7.1 内置Scheduler
QueueScheduler
队列调度器。
// 主队列
let mainScheduler = QueueScheduler.main
// 后台队列
let backgroundScheduler = QueueScheduler(
qos: .background,
name: "background.queue"
)
SignalProducer(value: 1)
.start(on: backgroundScheduler)
.observe(on: mainScheduler)
.startWithValues { value in
print(Thread.isMainThread) // true
}
UIScheduler
UI 调度器(主线程)。
let uiScheduler = UIScheduler()
SignalProducer(value: 1)
.observe(on: uiScheduler)
.startWithValues { value in
print(Thread.isMainThread) // true
}
7.2 start vs observe
- start:指定 SignalProducer 在哪个调度器上开始执行
- observe:指定观察者在哪个调度器上接收事件
SignalProducer { observer, lifetime in
print("执行线程: \(Thread.current)")
observer.send(value: 1)
observer.sendCompleted())
}
.start(on: QueueScheduler(qos: .background))
.observe(on: UIScheduler())
.startWithValues { value in
print("接收线程: \(Thread.current)")
}
8. 错误处理
8.1 错误类型
enum NetworkError: Error {
case invalidURL
case noData
case decodingError
}
8.2 错误处理操作符
catch
捕获错误并返回备用 SignalProducer。
SignalProducer<String, NetworkError>(error: .noData)
.catch { error -> SignalProducer<String, Never> in
print("捕获错误: \(error)")
return SignalProducer(value: "备用值")
}
.startWithValues { print($0) }
retry
重试失败的 SignalProducer。
var attempts = 0
SignalProducer<String, NetworkError> { observer, lifetime in
attempts += 1
if attempts < 3 {
observer.send(error: .noData)
} else {
observer.send(value: "成功")
observer.sendCompleted()
}
}
.retry(upTo: 2) // 最多重试 2 次
.start(
value: { print($0) },
failed: { print("错误: \($0)") }
)
flatMapError
将错误转换为值。
SignalProducer<String, NetworkError>(error: .noData)
.flatMapError { error in
SignalProducer(value: "错误: \(error)")
}
.startWithValues { print($0) }
9. 内存管理
9.1 Lifetime
Lifetime 用于管理 SignalProducer 的生命周期。
let producer = SignalProducer<String, Never> { observer, lifetime in
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
observer.send(value: "Tick")
}
lifetime.observeEnded {
timer.invalidate()
}
}
let disposable = producer.startWithValues { print($0) }
// 取消订阅时,timer 会自动失效
disposable.dispose()
9.2 避免循环引用
class ViewModel {
private let property = MutableProperty("")
func setup() {
property.signal.observeValues { [weak self] value in
self?.process(value)
}
}
private func process(_ value: String) {
// 处理数据
}
}
10. 与UIKit集成
10.1 Reactive扩展
ReactiveCocoa 为 UIKit 控件提供了 Reactive 扩展。
import ReactiveSwift
import ReactiveCocoa
class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var button: UIButton!
@IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// 文本输入绑定
label.reactive.text <~ textField.reactive.continuousTextValues
// 按钮点击
button.reactive.pressed = CocoaAction(Action { [weak self] _ in
return SignalProducer(value: "按钮点击")
})
}
}
10.2 常用绑定
// UILabel
label.reactive.text <~ property.producer.map { $0 }
// UITextField
textField.reactive.text <~ property.producer.map { $0 }
property <~ textField.reactive.continuousTextValues
// UIButton
button.reactive.pressed = CocoaAction(action)
// UISwitch
switch.reactive.isOn <~ property.producer.map { $0 }
property <~ switch.reactive.isOnValues
// UISlider
slider.reactive.value <~ property.producer.map { Float($0) }
property <~ slider.reactive.values.map { Int($0) }
11. 实际应用场景
11.1 网络请求
struct API {
static func fetchUser(id: Int) -> SignalProducer<User, NetworkError> {
let url = URL(string: "https://api.example.com/users/\(id)")!
return URLSession.shared.reactive.data(with: URLRequest(url: url))
.attemptMap { data, _ in
try JSONDecoder().decode(User.self, from: data)
}
.observe(on: UIScheduler())
}
}
API.fetchUser(id: 1)
.start(
value: { user in
print("用户: \(user)")
},
failed: { error in
print("错误: \(error)")
}
)
11.2 用户输入处理
class SearchViewModel {
let searchText = MutableProperty("")
let results = MutableProperty<[String]>([])
init() {
results <~ searchText.producer
.debounce(0.5, on: QueueScheduler.main)
.skipRepeats()
.filter { !$0.isEmpty }
.flatMap(.latest) { query -> SignalProducer<[String], Never> in
return self.search(query: query)
.flatMapError { _ in SignalProducer(value: []) }
}
}
private func search(query: String) -> SignalProducer<[String], NetworkError> {
// 实现搜索逻辑
return SignalProducer(value: ["结果1", "结果2"])
}
}
二、ReactiveCocoa框架源码解析
1. 架构设计
1.1 整体架构
ReactiveCocoa 采用协议导向的设计,核心是 Signal 和 SignalProducer。
Signal (热信号)
↓
Observer
↓
Event (value/failed/completed/interrupted)
SignalProducer (冷信号)
↓
Observer
↓
Signal
1.2 核心协议层次
// Signal 协议
protocol SignalProtocol {
associatedtype Value
associatedtype Error: Swift.Error
func observe(_ observer: Observer<Value, Error>) -> Disposable?
}
// SignalProducer 协议
protocol SignalProducerProtocol {
associatedtype Value
associatedtype Error: Swift.Error
func start(_ observer: Observer<Value, Error>) -> Disposable
}
2. Signal实现原理
2.1 Signal类实现
public final class Signal<Value, Error: Swift.Error>: SignalProtocol {
private let generator: (Observer<Value, Error>) -> Disposable?
private var observers: Bag<Observer<Value, Error>> = Bag()
private let lock = NSRecursiveLock()
public init(_ generator: @escaping (Observer<Value, Error>) -> Disposable?) {
self.generator = generator
}
public func observe(_ observer: Observer<Value, Error>) -> Disposable? {
lock.lock()
defer { lock.unlock() }
let token = observers.insert(observer)
// 如果是第一个观察者,开始生成事件
if observers.count == 1 {
let disposable = generator(Observer { [weak self] event in
self?.send(event)
})
return CompositeDisposable(
disposable,
Disposable { [weak self] in
self?.lock.lock()
self?.observers.remove(using: token)
self?.lock.unlock()
}
)
}
return Disposable { [weak self] in
self?.lock.lock()
self?.observers.remove(using: token)
self?.lock.unlock()
}
}
private func send(_ event: Event<Value, Error>) {
lock.lock()
let currentObservers = observers
lock.unlock()
for observer in currentObservers {
observer.send(event)
}
// 如果是终止事件,清理观察者
if event.isTerminating {
lock.lock()
observers.removeAll()
lock.unlock()
}
}
}
关键点:
- Signal 是引用类型(class)
- 使用
Bag存储多个观察者 - 使用锁保护共享状态
- 第一个观察者订阅时开始生成事件
2.2 pipe实现
extension Signal {
public static func pipe() -> (Signal<Value, Error>, Observer<Value, Error>) {
let observer = Observer<Value, Error>()
let signal = Signal<Value, Error> { observer in
// 将外部 observer 的事件转发给内部 observer
return observer.observe { event in
observer.send(event)
}
}
return (signal, observer)
}
}
关键点:
pipe创建 Signal 和 Observer 对- Observer 可以手动发送事件
- 适合将命令式代码转换为响应式代码
3. SignalProducer实现原理
3.1 SignalProducer结构
public struct SignalProducer<Value, Error: Swift.Error>: SignalProducerProtocol {
private let startHandler: (Observer<Value, Error>, Lifetime) -> Void
public init(_ startHandler: @escaping (Observer<Value, Error>, Lifetime) -> Void) {
self.startHandler = startHandler
}
public func start(_ observer: Observer<Value, Error>) -> Disposable {
let lifetime = Lifetime()
let compositeDisposable = CompositeDisposable()
lifetime.observeEnded {
compositeDisposable.dispose()
}
startHandler(observer, lifetime)
return compositeDisposable
}
}
关键点:
- SignalProducer 是值类型(struct)
- 每次
start都会创建新的 Signal - 使用
Lifetime管理资源生命周期
3.2 SignalProducer转换
extension SignalProducer {
public var signal: Signal<Value, Error> {
return Signal { observer in
return self.start(observer)
}
}
}
extension Signal {
public var producer: SignalProducer<Value, Error> {
return SignalProducer { observer, lifetime in
let disposable = self.observe(observer)
lifetime.observeEnded {
disposable?.dispose()
}
}
}
}
关键点:
- SignalProducer 可以转换为 Signal
- Signal 可以转换为 SignalProducer
- 转换是延迟的,不会立即执行
4. Property实现原理
4.1 Property协议
public protocol PropertyProtocol {
associatedtype Value
var value: Value { get }
var signal: Signal<Value, Never> { get }
var producer: SignalProducer<Value, Never> { get }
}
4.2 MutableProperty实现
public final class MutableProperty<Value>: MutablePropertyProtocol {
private let lock = NSRecursiveLock()
private var _value: Value
private let observer: Observer<Value, Never>
private let signal: Signal<Value, Never>
public var value: Value {
get {
lock.lock()
defer { lock.unlock() }
return _value
}
set {
lock.lock()
let oldValue = _value
_value = newValue
lock.unlock()
if oldValue != newValue {
observer.send(value: newValue)
}
}
}
public init(_ value: Value) {
_value = value
let (signal, observer) = Signal<Value, Never>.pipe()
self.signal = signal
self.observer = observer
// 立即发送初始值
observer.send(value: value)
}
public var producer: SignalProducer<Value, Never> {
return SignalProducer { observer, lifetime in
// 立即发送当前值
observer.send(value: self.value)
// 观察后续变化
let disposable = self.signal.observe(observer)
lifetime.observeEnded {
disposable?.dispose()
}
}
}
}
关键点:
- MutableProperty 是引用类型
- 使用锁保护
_value - 值变化时发出事件
- producer 会立即发送当前值
4.3 绑定操作符实现
infix operator <~ : BindingPrecedence
public func <~ <Source: SignalProducerProtocol, Destination: BindingTargetProtocol>(
destination: Destination,
source: Source
) -> Disposable
where Source.Value == Destination.Value, Source.Error == Never {
return source.startWithValues { value in
destination.consume(value)
}
}
public func <~ <Source: SignalProtocol, Destination: BindingTargetProtocol>(
destination: Destination,
source: Source
) -> Disposable?
where Source.Value == Destination.Value, Source.Error == Never {
return source.observeValues { value in
destination.consume(value)
}
}
关键点:
<~操作符实现单向绑定- 自动管理订阅生命周期
- 支持 Signal 和 SignalProducer
5. Action实现原理
5.1 Action结构
public final class Action<Input, Output, Error: Swift.Error> {
private let executeClosure: (Input) -> SignalProducer<Output, Error>
private let isEnabledProperty: MutableProperty<Bool>
private let eventsObserver: Observer<Event<Output, Error>, Never>
public let isEnabled: Property<Bool>
public let isExecuting: Property<Bool>
public let values: Signal<Output, Never>
public let errors: Signal<Error, Never>
public let events: Signal<Event<Output, Error>, Never>
public init(enabledIf: Property<Bool> = Property(value: true),
execute: @escaping (Input) -> SignalProducer<Output, Error>) {
self.executeClosure = execute
self.isEnabledProperty = MutableProperty(true)
self.isEnabled = Property(capturing: isEnabledProperty)
let (eventsSignal, eventsObserver) = Signal<Event<Output, Error>, Never>.pipe()
self.events = eventsSignal
self.eventsObserver = eventsObserver
self.values = events.map { $0.value }.skipNil()
self.errors = events.map { $0.error }.skipNil()
let isExecutingProperty = MutableProperty(false)
self.isExecuting = Property(capturing: isExecutingProperty)
// 监听执行状态
events.observeValues { event in
switch event {
case .value:
isExecutingProperty.value = true
case .completed, .failed, .interrupted:
isExecutingProperty.value = false
}
}
}
public func apply(_ input: Input) -> SignalProducer<Output, Error> {
return SignalProducer { observer, lifetime in
guard self.isEnabled.value else {
observer.sendInterrupted()
return
}
let producer = self.executeClosure(input)
let disposable = producer.start { event in
self.eventsObserver.send(value: event)
observer.send(event)
}
lifetime.observeEnded {
disposable.dispose()
}
}
}
}
关键点:
- Action 封装异步操作
- 提供执行状态(isEnabled、isExecuting)
- 提供值、错误、事件流
- 可以禁用 Action
6. Operators实现原理
6.1 map实现
extension SignalProducer {
public func map<U>(_ transform: @escaping (Value) -> U) -> SignalProducer<U, Error> {
return SignalProducer { observer, lifetime in
self.start { event in
switch event {
case .value(let value):
observer.send(value: transform(value))
case .failed(let error):
observer.send(error: error)
case .completed:
observer.sendCompleted()
case .interrupted:
observer.sendInterrupted()
}
}
}
}
}
关键点:
- map 创建新的 SignalProducer
- 转换每个值事件
- 保持其他事件不变
6.2 filter实现
extension SignalProducer {
public func filter(_ predicate: @escaping (Value) -> Bool) -> SignalProducer<Value, Error> {
return SignalProducer { observer, lifetime in
self.start { event in
switch event {
case .value(let value):
if predicate(value) {
observer.send(value: value)
}
case .failed(let error):
observer.send(error: error)
case .completed:
observer.sendCompleted()
case .interrupted:
observer.sendInterrupted()
}
}
}
}
}
关键点:
- filter 创建新的 SignalProducer
- 只转发满足条件的值
- 保持其他事件不变
6.3 flatMap实现
extension SignalProducer {
public func flatMap<U>(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> SignalProducer<U, Error>) -> SignalProducer<U, Error> {
return SignalProducer { observer, lifetime in
let flattenProducer = self.map(transform).flatten(strategy)
let disposable = flattenProducer.start(observer)
lifetime.observeEnded {
disposable.dispose()
}
}
}
}
关键点:
- flatMap 支持多种策略(.latest、.merge、.concat)
- 管理多个内部 SignalProducer
- 需要复杂的生命周期管理
7. Schedulers实现原理
7.1 Scheduler协议
public protocol Scheduler {
func schedule(_ action: @escaping () -> Void) -> Disposable?
func schedule(after date: Date, action: @escaping () -> Void) -> Disposable?
func schedule(after date: Date, interval: TimeInterval, action: @escaping () -> Void) -> Disposable?
}
7.2 QueueScheduler实现
public final class QueueScheduler: Scheduler {
public let queue: DispatchQueue
public init(qos: DispatchQoS = .default, name: String = "org.reactivecocoa.ReactiveSwift.QueueScheduler") {
self.queue = DispatchQueue(label: name, qos: qos)
}
public static let main = QueueScheduler(queue: .main, name: "org.reactivecocoa.ReactiveSwift.QueueScheduler.main")
public func schedule(_ action: @escaping () -> Void) -> Disposable? {
let disposable = SimpleDisposable()
queue.async {
if !disposable.isDisposed {
action()
}
}
return disposable
}
public func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? {
let disposable = SimpleDisposable()
let timeInterval = date.timeIntervalSinceNow
queue.asyncAfter(deadline: .now() + timeInterval) {
if !disposable.isDisposed {
action()
}
}
return disposable
}
}
关键点:
- QueueScheduler 使用 DispatchQueue
- 支持立即和延迟调度
- 支持取消调度
8. 生命周期管理
8.1 Lifetime实现
public final class Lifetime {
private let token: Token
private var observers: Bag<() -> Void> = Bag()
private let lock = NSRecursiveLock()
public init() {
token = Token()
}
public func observeEnded(_ action: @escaping () -> Void) {
lock.lock()
let isEnded = token.isEnded
if !isEnded {
observers.insert(action)
}
lock.unlock()
if isEnded {
action()
}
}
deinit {
token.markEnded()
lock.lock()
let currentObservers = observers
observers.removeAll()
lock.unlock()
for observer in currentObservers {
observer()
}
}
}
关键点:
- Lifetime 管理资源生命周期
- 对象释放时自动执行清理操作
- 使用
observeEnded注册清理回调
8.2 Disposable管理
public final class CompositeDisposable: Disposable {
private var disposables: [Disposable] = []
private let lock = NSRecursiveLock()
private var isDisposed = false
public init(_ disposables: Disposable...) {
self.disposables = disposables
}
public func add(_ disposable: Disposable?) {
guard let disposable = disposable else { return }
lock.lock()
if isDisposed {
lock.unlock()
disposable.dispose()
return
}
disposables.append(disposable)
lock.unlock()
}
public func dispose() {
lock.lock()
guard !isDisposed else {
lock.unlock()
return
}
isDisposed = true
let currentDisposables = disposables
disposables.removeAll()
lock.unlock()
for disposable in currentDisposables {
disposable.dispose()
}
}
}
关键点:
- CompositeDisposable 管理多个 Disposable
- 线程安全
- 一次性释放所有资源
9. 性能优化策略
9.1 值类型优化
SignalProducer 是值类型,避免堆分配:
// 值类型,零成本抽象
struct SignalProducer<Value, Error: Swift.Error> { }
9.2 延迟执行
SignalProducer 延迟创建 Signal:
let producer = SignalProducer<String, Never> { observer, lifetime in
// 只在 start 时执行
observer.send(value: "Hello")
}
9.3 共享执行
使用 share() 共享 SignalProducer:
let shared = expensiveProducer().share()
shared.startWithValues { } // 订阅1
shared.startWithValues { } // 订阅2(共享执行)
9.4 内存优化
- 使用
weak引用避免循环引用 - 使用
Lifetime自动管理资源 - 及时释放不需要的订阅
📚 总结
ReactiveCocoa 的核心优势
- Property 状态管理:提供 Property 和 MutableProperty 管理状态
- Action 模式:提供 Action 处理用户交互和异步操作
- 类型安全:充分利用 Swift 类型系统
- 生命周期管理:使用 Lifetime 自动管理资源
- UIKit 集成:深度集成 UIKit 控件
学习建议
- 理解 Signal vs SignalProducer:掌握热信号和冷信号的区别
- 理解 Property:掌握状态管理
- 理解 Action:掌握用户交互处理
- 阅读源码:深入理解实现原理
- 实际应用:在项目中应用 ReactiveCocoa
文档版本:v1.0
最后更新:2026年1月15日
参考文献:ReactiveCocoa GitHub Repository, ReactiveSwift Source Code