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

この記事からわかること

  • RxSwiftObservableクラスとは?
  • subscribeメソッド使い方
  • asObservableメソッドの使い方
  • 検知できるイベント種類
  • Observableを生成できるcreateメソッドなど

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

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
    }
}

引用:GitHub/Observable.swift

ここではsubscribeasObservable2つのメソッドを確認できます。これについては後述します。

検知できるイベント

Observableクラスで検知できるイベントは以下の3種類です。


@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
}

引用:GitHub/Event.swift

onNextイベントの発生のたびに複数回検知される可能性があり、onErrorまたはonCompletedストリームの中でどちらか1回しか観測されません。そしてonErrorまたはonCompletedのどちらかを検知したタイミングまたは明示的に指定したタイミングで監視は終了します。

onNextにはイベントの発生(通知)とともに任意の値を格納して渡すことができます。格納する値は通知のたびに異なる値を含めることができます。マーブルダイアグラムに表すと以下のような感じになります。1つのストリームの中に様々な値を保持したイベントが発生し、最後にエラーか完了通知が発生すると役目を終えます。

RxSwiftとは?導入方法と使い方まとめ!ストリームを理解する

subscribeメソッド

イベントを検知して処理を行うためには2人の登場人物が必要になります。それが「観測される側(Subject)」と「観測する側(Observer)」です。(オブザーバーパターン)

subscribeは日本語で「購読」という意味を持つ英単語です。Observableクラスのsubscribeメソッドを実行することで対象のObservableクラスの観測が開始され各引数の中で各イベントを取得できます。

RxSwiftとは?導入方法と使い方まとめ!ストリームを理解する

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

RxSwiftとは?導入方法と使い方まとめ!ストリームを理解する

実際のコード

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))
    }
}

引用:GitHub/ObserverType.swift

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

他にもいろいろあるので公式を参考に確認してみてください。

GitHub:RxSwift/Observables/

Subject

SubjectとはRxSwiftにおけるイベントの検知と発生が可能なクラスです。RxSwiftにおいてイベントの検知が可能なクラスといえばObservableクラスですがさらに自身でイベント流せるのが大きな違いです。詳しくは以下の記事を参考にしてください。

おすすめ記事:【RxSwift】Subjectとは?Relayとの違いと使い方

ご覧いただきありがとうございました。

参考文献:RxSwiftCommunity
参考文献:RxSwiftについてようやく理解できてきたのでまとめることにした(2)

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index