嗨,大家好,今天接著聊聊Subject!
Relay在某些情況很好用,比如說在非Rx跟Rx之間的轉換,又或是說,Imperative世界與Rx世界的橋樑,假設像下方這樣
let image = BehaviorRelay<[UIImage]>(value: [])
// 把一組圖片轉成Rx
image.accept(images)
// 清空image
image.accept([])
// 新增一張圖片
var current = image.value
current.append(newImage)
image.accept(current)
Erik Meijer是一個對Rx有莫大貢獻的大神,在網路上能找到許多關於他的影片跟文章,他曾經說過
Subjects are the “mutable variables" of the Rx world and in most cases you do not need them. – Erik Meijer
大意就是說,Subjects是個可變的變數,當你使用Subject或Relay請確定是不是真的需要它,這其他文章也可以看到類似討論 Why Does E.Meijer not like Subjects? 跟 Top mistakes in RxSwift you want to avoid - Code in a suit。
還記得第一天,我們說Rx世界是Stateless,所有東西就是input跟output,大多數情況都可以用.create
搭配其他operator解決,但因為Subject跟Relay太好用了,剛開始我們常常會這樣
Observable
.subscribe(onNext: {
observerA.onNext(...)
observerB.onNext(...)
observerC.onNext(...)
})
.disposed(by: disposeBag)
或是
relay.accept(a)
relay.accept(b)
relay.accept(c)
你會發現,Subject在同個class或是不同class被到處被onNext()
,Relay被到處.accept()
,這樣我們又回到Imperative思維,並且在Imperative上包一層的感覺,反而更不舒服,寫久了會很亂,也會常常出錯。
我自己呢,因為功力不足,不得已的時候還是會用,但要『切記做好封裝』,封裝成class,對內設為private,想怎麼用都可以,對外是Observable,給外部使用,大概會像這樣
private let imageRelay = BehaviorRelay<[UIImage]>(value: [])
private(set) lazy var image = imageRelay.asObservable()
或是這樣
let image: Observable<[UIImage]>
init() {
let imageRelay = BehaviorRelay<[UIImage]>(value: [])
image = imageRelay.asObservable()
}
明天開始進入各種operator的介紹,就這樣,掰掰!