【RxSwift】Observableクラスとは?subscribeメソッドの使い方!

この記事からわかること
- RxSwiftのObservableクラスとは?
- subscribeメソッドの使い方
- asObservableメソッドの使い方
- 検知できるイベントの種類
- Observableを生成できるcreateメソッドなど
index
[open]
\ アプリをリリースしました /
RxSwiftのObservableクラスの概要と使い方などをまとめていきます。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
おすすめ記事:【RxSwiftとは?導入方法と使い方まとめ!ストリームを理解する
Observableクラスとは?
そもそもObservableとは日本語で「観測可能」を意味する英単語です。ReactiveXではストリームを観測、検知可能なクラスのことをObservableと呼び変化やエラー、完了を検知すると観測者に対して通知してくれます。RxSwiftではObservable
クラスとして定義されています。
public class Observable<Element> : ObservableType {
init() {
#if TRACE_RESOURCES
_ = Resources.incrementTotal()
#endif
}
public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
rxAbstractMethod()
}
public func asObservable() -> Observable<Element> { self }
deinit {
#if TRACE_RESOURCES
_ = Resources.decrementTotal()
#endif
}
}
ここではsubscribe
とasObservable
の2つのメソッドを確認できます。これについては後述します。
検知できるイベント
Observableクラスで検知できるイベントは以下の3種類です。
- onNext:イベント(値を格納できる)
- onError:エラー
- onCompleted:完了
@frozen public enum Event<Element> {
/// Next element is produced.
case next(Element)
/// Sequence terminated with an error.
case error(Swift.Error)
/// Sequence completed successfully.
case completed
}
onNext
はイベントの発生のたびに複数回検知される可能性があり、onError
またはonCompleted
はストリームの中でどちらか1回しか観測されません。そしてonError
またはonCompleted
のどちらかを検知したタイミングまたは明示的に指定したタイミングで監視は終了します。
onNext
にはイベントの発生(通知)とともに任意の値を格納して渡すことができます。格納する値は通知のたびに異なる値を含めることができます。マーブルダイアグラムに表すと以下のような感じになります。1つのストリームの中に様々な値を保持したイベントが発生し、最後にエラーか完了通知が発生すると役目を終えます。

subscribeメソッド
イベントを検知して処理を行うためには2人の登場人物が必要になります。それが「観測される側(Subject)」と「観測する側(Observer)」です。(オブザーバーパターン)
- 「観測される側 = Observableクラス」
- 「観測する側 = subscribeメソッドで発行」
subscribeは日本語で「購読」という意味を持つ英単語です。Observable
クラスのsubscribe
メソッドを実行することで対象のObservable
クラスの観測が開始され各引数の中で各イベントを取得できます。

例えばTextFieldの入力イベントを観測しLabelのテキストにバインディングさせる場合を見てみます。この場合は入力されるたびにonNext
が発火され観測者に対して通知が送られます。観測者はその通知を元に定義されている処理(ここではUILabelに適応)を実行します。

実際のコード
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel()
label.frame = CGRect(x:130, y:200,width:200, height:50)
label.text = "placeholder..." // textField.text とBindingされるので表示されることはない
self.view.addSubview(label)
let textField = UITextField()
textField.frame = CGRect(x:130, y:300,width:200, height:50)
textField.borderStyle = UITextField.BorderStyle.line
self.view.addSubview(textField)
let text = textField.rx.text.asObservable() // Observableクラスの取得
text.subscribe(onNext: { [weak self] text in
label.text = text // 変化した値をUIとリンク
}, onError: { _ in
print("error")
}, onCompleted: {
print("completed")
}).disposed(by: disposeBag)
}
}
asObservableメソッド
asObservable
メソッドは自身であるObservableクラスを返すメソッドです。
let text = textField.rx.text.asObservable() // Observableクラスの取得
print(type(of: text)) // SubscribeOn<Observable<Optional<String>>>
Dispose:購読の廃棄
subscribe
メソッドで購読を開始したObservableクラスをそのまま観測しつづけるとメモリリークの原因になるので任意のタイミングで購読を終了させる必要があります。これを「Dispose(廃棄)」と呼びます。
購読が廃棄されるタイミングは明示的に廃棄処理を行った時かonErrorまたはonCompletedが呼ばれイベントが終了した時です。
subscribeメソッドの定義をもう一度みてみると返り値がDisposable
クラスとなっています。このインスタンスからdispose()
メソッドを呼び出すことで購読を廃棄することができます。
public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
rxAbstractMethod()
}
しかし実際に明示的にdispose()
メソッドを呼び出すことは少なくDisposeBag
クラスを使用して一括で購読を廃棄する方法が使用されます。
おすすめ記事:【RxSwift】DisposeBagクラスの使い方!Disposable
Observableクラスの使用方法
TextFieldの入力値を観測する際はObservableクラスが目に見えずらかったのでObservableクラスを使用してイベントを発生させるコードを実装してみます。ViewControllerクラスを用意してライブラリをimport
しておきます。
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
Observableクラスをインスタンス化する際にはObservable<Element>
形式で型を指定します。ここで指定したデータ型をonNextで渡せるようになります。複数の型を渡したいときはタプルなどを使用すればOKです。
Observableクラスの生成
Observableクラスを生成するにはcreate
メソッドを使用します。引数subscribe
の中に渡すクロージャの中ではAnyObserver
型を受け取ることができそこから各イベントを定義できます。最終的にこのメソッドはObservableオブジェクトを返します。
public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable) -> Observable<Element> {
AnonymousObservable(subscribe)
}
イベント名称そのままのメソッドが用意されておりonNext
メソッドでは引数に渡したい値を記述します。この値はObservable<Element>
形式で定義した型と同じである必要があります。
override func viewDidLoad() {
super.viewDidLoad()
let observable = Observable<String>.create { observer in
observer.onNext("イベント1発火")
observer.onNext("イベント2発火")
observer.onCompleted()
return Disposables.create()
}
}
ObserverTypeに定義されているメソッド
extension ObserverType {
public func onNext(_ element: Element) {
self.on(.next(element))
}
public func onCompleted() {
self.on(.completed)
}
public func onError(_ error: Swift.Error) {
self.on(.error(error))
}
}
create
メソッド以外にも生成するメソッドは存在します。
購読の開始と処理の定義
これでObservableオブジェクトを取得(生成)できたのでsubscribe
メソッドを使用して購読を開始し、イベントごとに実行したい処理を定義していきます。
subscribe
メソッドでは各引数の中のクロージャからイベントから渡されるデータを参照できます。そして最後にdisposed
メソッドを呼び出し引数にDisposeBagオブジェクトを渡します。
observable.subscribe (onNext: { value in
print("\(value):next")
}, onError: { _ in
print("error")
}, onCompleted: {
print("completed")
}).disposed(by: disposeBag)
この段階ではエラーdisposeBag
を定義していないためエラーが発生してしまうのでDisposeBagインスタンスをプロパティとして用意しておきます。
DisposeBag
DisposeBagの詳細な説明はここでは割愛しますが「ゴミ箱」とよく表現されます。不要になり廃棄したい観測中のObservableオブジェクトを格納しておき任意のタイミングで一括で削除するイメージです。
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let observable = Observable<String>.create { observer in
observer.onNext("イベント1発火")
observer.onNext("イベント2発火")
observer.onCompleted()
return Disposables.create()
}
observable.subscribe (onNext: { value in
print(value)
print("next")
}, onError: { _ in
print("error")
}, onCompleted: {
print("completed")
}).disposed(by: disposeBag)
}
}
Observableの生成
create
メソッドはイベントの回数や種類を記述できるフレキシブルなメソッドでした。RxSwiftではそれ以外にもObservableクラスを生成するメソッドが複数用意されています。
just
例えばjust
メソッドはonNextとonCompletedを1回ずつ発行します。create
メソッドでも同じ挙動を実装することは可能ですがjust
メソッドを使用すると1行で済ませることができます。
let observable = Observable<String>.just("イベント発火 & Completed")
from
公式リファレンス:GitHub:RxSwift/Sequence.swift
from
メソッドを使用することで配列の値を元に自動で要素数分のonNextとonCompletedを発行してくれます。
let observable = Observable<Int>.from([1,2,3])
1:next
2:next
3:next
completed
他にもいろいろあるので公式を参考に確認してみてください。
Subject
SubjectとはRxSwiftにおけるイベントの検知と発生が可能なクラスです。RxSwiftにおいてイベントの検知が可能なクラスといえばObservable
クラスですがさらに自身でイベント流せるのが大きな違いです。詳しくは以下の記事を参考にしてください。
おすすめ記事:【RxSwift】Subjectとは?Relayとの違いと使い方
ご覧いただきありがとうございました。
参考文献:RxSwiftCommunity
参考文献:RxSwiftについてようやく理解できてきたのでまとめることにした(2)