[RxSwift]SubjectとRelayの違い
経緯
どちらもObservableのイベント検知から、
イベントを流すことまで可能なクラスですが、
時間経過と共にどちらを使用すべきか調べ直している気がしていて、
改めてしっかりと違いを整理しておきたかったため。
Subject
Subjectは以下の3種類のイベントを流すことができます。
onNext
, onError
, onComplete
こちらの3種類のイベントについては、
後ほど詳しく記載します。
それからSubjectには以下の2種類があり、
- PublishSubject
- BehaviorSubject
このPublish
とBehavior
は後述するRelayにも存在します。
違いに関しては後ほど記載します。
Relay
RelayにはSubjectではあった種類のイベントは無く、
onNext
のみ流すことが可能です。
onError
やonComplete
は流れてこないことが保証されています。
それからRelayにもPublish
とBehavior
の2種類があります。
上記onNext
に値を流す方法は、accept
を使用します。
let publishRelay = PublishRelay<Int>()
publishRelay.subscribe { num in
print(num)
}.disposed(by: disposeBag)
publishRelay.accept(99)
3種類のイベントについて
以下の公式のソースコードを見てみると理解が深まるかと思います。
実際のソースはこちら。//
// ObserverType.swift
// RxSwift
//
// Created by Krunoslav Zaher on 2/8/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Supports push-style iteration over an observable sequence.
public protocol ObserverType {
/// The type of elements in sequence that observer can observe.
associatedtype Element
/// Notify observer about sequence event.
///
/// - parameter event: Event that occurred.
func on(_ event: Event<Element>)
}
/// Convenience API extensions to provide alternate next, error, completed events
extension ObserverType {
/// Convenience method equivalent to `on(.next(element: Element))`
///
/// - parameter element: Next element to send to observer(s)
public func onNext(_ element: Element) {
self.on(.next(element))
}
/// Convenience method equivalent to `on(.completed)`
public func onCompleted() {
self.on(.completed)
}
/// Convenience method equivalent to `on(.error(Swift.Error))`
/// - parameter error: Swift.Error to send to observer(s)
public func onError(_ error: Swift.Error) {
self.on(.error(error))
}
}
onNext
は引数でElement
を送り、
onError
はSwift.Error
を送ります。
onComplete
は何も送ることはなくそのイベントのみです。
PublishとBehaviorの違い
Behaviorは、subscribe時に1つ直前のイベントを受け取ることが可能で、
最初にsubcribeするときは、設定した初期値を受け取ることになります。
反対にPublishの場合は初期値を持たず、過去のイベントは流れません。
この過去の値や初期値のことをバッファが有無でよく記載されます。
// バッファ有
let behaviorSubject = BehaviorSubject<Int>(value: 1)
// バッファ無
let publishRelay = PublishSubject<Int>()
まとめ
このように大きく分けSubjectとRelayの違いを説明しましたが、
その中にPublishとBehaviorでも違いがあるので、
適切なものを定義していきたいです。
Discussion