【Swift UI/Combine】PassthroughSubjectとは?store(in:)メソッド

この記事からわかること
- SwiftのCombineフレームワーク
- PassthroughSubjectの特徴と使い方
- CurrentValueSubjectとの違い
- store(in:)メソッドの使い方
- &(アンパサンド)とは?
index
[open]
\ アプリをリリースしました /
SwiftのCombineフレームワークのPassthroughSubject
についてまとめていきます。まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
PassthroughSubjectとは?
PassthroughSubject
とは非同期処理やデータバインディングなどための機能を提供するCombineフレームワークのPublisherの1つです。Publisherはデータストリームを生成するためのオブジェクトであり、時間の経過と共に変化する一連の値の変化を配信(通知を送信)する特徴があります。

さらにPublisherの中のSubject(被写体)にカテゴライズされるのがPassthroughSubject
です。Combineフレームワークで定義されているSubject
とは「Publisherプロトコルを継承し、値を発行する役割」と、「他のPublisherが送信するデータストリームを受け取るSubscriber」の両方の役割を持つオブジェクトです。
同じSubjectの仲間にCurrentValueSubject
が定義されています。Combineフレームワークに関するPublisherやSubject、ストリームなどたくさんの単語が出てきましたが詳細は以下を参考にしてください。
おすすめ記事:【Swift UI】Combineフレームワークの使い方!PublisherとSubscriberの違い
PassthroughSubject:ここまでのまとめ
- CombineフレームワークのPublisherの1つ
- Publisherの中のSubject(被写体)にカテゴライズ
- 値の発行と購読、両方可能
特徴とCurrentValueSubjectとの違い
CurrentValueSubject
とPassthroughSubject
、2つの大きな違いは値を保持するかどうかです。
- CurrentValueSubject:最新値を常に保持し、出力時に最新値が出力
- PassthroughSubject:値を保持せず、受け取ったら値をそのまま出力
CurrentValueSubjectは常に最新値を保持してくれるのでログイン状態や設定値など参照する可能性のある場合に活用できそうです。
PassthroughSubjectは値自体を保持しないので常に最新の値に更新され続けるようなWeb API取得や一度きりの状態変化を取得したい場合などが良いのかもしれません。
PassthroughSubjectの役割
PassthroughSubject
クラスは値の変更を検知する箱のようなイメージです。箱の中に値が格納されたことを周りに知らせる(ブロードキャストする)役割(sendメソッド)や、その箱の変更を観測し変更があった場合に任意の処理を行わせる役割(sinkメソッド)が用意されています。
例えば以下はPassthroughSubject
クラスを使用した例です。
PassthroughSubject
は定義の通り、<Output, Failure>
の2つのデータ型を保持します。Output
にはString
やInt
、値が存在しないVoid
などを渡すことができ、Failure
には任意のエラー型を渡すことが可能です。
Swift UIで使用してみる
Swift UIの中で使用してみたいと思います。今回はWebPageState
クラスのプロパティにPassthroughSubject
クラスを適応させてみたいと思います。またアプリ内でシングルトンになるようにshared
プロパティを定義しておきます。
異なるView同士でイベント通知を検知し合えるのがメリットの1つなので2つのビューを定義してみました。本来ならそれぞれのViewModelを介することが多いかもしれませんがわかりやすくそのまま使用しています。TestWebView
側ではonAppear
のタイミングで購読を開始しています。この際に返却されるAnyCancellable
オブジェクトをViewのプロパティに格納しておきます。
発行する側は特に変わったところはありません。このように異なるViewやクラスなどからイベントを検知してそれに伴う処理が実行できるようになります。
管理する対象を増やす
ではWebPageState
クラスにPassthroughSubject
を追加してみます。
単純に以下のように実装するとcancellable
の中身が上書きされてreload
がイベントを検知できなくなってしまいます。
store(in: &cancellables)
動作するようにするにはstore(in:)
メソッドを使用します。このメソッドはAnyCancellable
をSetの中に自動で格納してくれます。定義を見てみるとinout
が指定されているので「参照渡し」になります。呼び出す際には&
(アンパサンド)を変数の前に付与する必要があります。
実装コードは以下のようになります。キャンセルする方法もremoveAll
メソッドに変更しています。
ご覧いただきありがとうございました。