目录
前言
1.什么是 BehaviorRelay
2.基本使用方式
3.BehaviorRelay的常用API
4.BehaviorRelay 和其它类型的对比
5.BehaviorRelay的使用场景
1.绑定UITableView
2.MVVM 场景下使用 BehaviorRelay
6.使用注意事项以及建议
1.注意事项
2.使用建议总结
7.推荐阅读
前言
在 iOS 开发中,使用 RxSwift 构建响应式架构(如 MVVM)越来越流行。我们经常会遇到“需要持有某个状态值,并且随时通知观察者”的需求,这时你会发现 BehaviorRelay 几乎无处不在。
今天这篇文章,我们就来深入剖析 BehaviorRelay 是什么、怎么用、适合用在什么场景中,以及实战中的最佳实践。
1.什么是 BehaviorRelay
BehaviorRelay 是 RxCocoa 中封装的一个类,用于代替旧版的 Variable(已废弃)。它有以下几个特点:
-
持有当前值,可以通过 .value 获取
-
可以更新值,使用 .accept(_:) 方法
-
可以对外暴露为Observable
-
不会发送 error或completed,所以永远不会中断
本质上,它是对 RxSwift 的 BehaviorSubject 的一个安全封装,去掉了 .onError() 和 .onCompleted(),适合用作状态容器。
2.基本使用方式
import RxSwift
import RxCocoalet disposeBag = DisposeBag()// 1. 创建一个初始值为 0 的 BehaviorRelay
let relay = BehaviorRelay<Int>(value: 0)// 2. 订阅它
relay.asObservable().subscribe(onNext: { value inprint("当前值:\(value)")}).disposed(by: disposeBag)// 3. 修改它的值
relay.accept(1) // 输出:当前值:1
relay.accept(5) // 输出:当前值:5
3.BehaviorRelay的常用API
API | 说明 |
---|---|
.value | 当前持有的值(同步获取) |
.accept(_:) | 接受一个新值,会触发订阅回调 |
.asObservable() | 转为只读的 Observable,防止外部直接修改 |
.bind(to:) / .drive(_:) | 可以与 UI 控件绑定 |
4.BehaviorRelay 和其它类型的对比
特性 | BehaviorRelay | PublishRelay | BehaviorSubject |
---|---|---|---|
持有当前值 | ✅ 是 | ❌ 否 | ✅ 是 |
获取当前值 | ✅ .value | ❌ 无 | ✅ .value |
是否可变 | ✅ .accept() | ✅ .accept() | ✅ .onNext() |
是否会终止 | ❌ 不会 | ❌ 不会 | ✅ .onCompleted() 或 .onError() |
推荐场景 | 状态管理 | 事件传递 | 不推荐直接使用(易误用) |
5.BehaviorRelay的使用场景
1.绑定UITableView
let items = BehaviorRelay<[String]>(value: ["苹果", "香蕉", "橘子"])items.bind(to: tableView.rx.items(cellIdentifier: "cell")) { row, element, cell incell.textLabel?.text = element}.disposed(by: disposeBag)// 添加新元素
var current = items.value
current.append("榴莲")
items.accept(current) // 表格会自动刷新
✅ BehaviorRelay 是 TableView/CollectionView 数据源绑定的理想选择。
2.MVVM 场景下使用 BehaviorRelay
在MVVM架构中,我们常常把 BehaviorRelay 放到 ViewModel 中作为状态容器:
class ContactListViewModel {let contacts = BehaviorRelay<[String]>(value: [])func addContact(_ name: String) {var list = contacts.valuelist.append(name)contacts.accept(list)}
}
ViewController 中绑定:
viewModel.contacts.bind(to: tableView.rx.items(cellIdentifier: "cell")) { row, name, cell incell.textLabel?.text = name}.disposed(by: disposeBag)
6.使用注意事项以及建议
1.注意事项
-
不要滥用 .accept(),应限制数据修改权限在 ViewModel 或管理器中
-
.value 是同步获取,不会触发订阅回调
-
若只需要事件传递(如点击),请用 PublishRelay,不要用 BehaviorRelay
-
BehaviorRelay 永远不会发送 .completed 或 .error,也无法手动终止它
2.使用建议总结
场景 | 是否推荐使用 BehaviorRelay |
---|---|
表示状态(布尔、列表、数值等) | ✅ 推荐 |
控制 UI 状态(按钮是否可点等) | ✅ 推荐 |
事件传递(点击事件、跳转等) | ❌ 不推荐 → 用 PublishRelay |
需要流结束、错误处理的场景 | ❌ 不适合 → 用 Observable 或 Subject |
7.推荐阅读
-
RxSwift 官方文档
-
RxCocoa BehaviorRelay 源码