目錄
前言
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 源碼