【Swift/Combine】flatMapメソッドの使い方!publisherを直列処理

この記事からわかること
- SwiftのCombineフレームワーク
- flatMapメソッドの使い方
- 非同期処理を直列に実行する方法
\ アプリをリリースしました /
環境
- Xcode:16.0
- iOS:18.0
- Swift:5.9
- macOS:Sonoma 14.6.1
flatMapメソッドとは?
CombineのflatMap
メソッドは上流から流れてきた複数のpublisherの値を整形して新しいpublisherを下流へ流すメソッドです。これによりpublisherを直列に繋げたり、上流からの値を元に新規でpublisherを作成したりすることができるようになります。
引数maxPublishers
には並列に処理をするpublisherの数を指定できます。初期値は無制限unlimited
です。
引数transform
部分で上流のpublisher(非同期処理)の出力値(Self.Output)を参照し、下流へPublisherを流すことができます。
またflatMap
で指定したpublisher
は上流のpublisher
が成功した場合のみ実行されます。エラーが発生した場合はそのエラーを下流に伝播します。
使い方
flatMap
の使い方を見てみます。Just
で生成したパイプラインに直列で非同期処理を挟んでいきます。flatMap
内では上流の結果を参照でき、そこから新しいpublisherを生成して下流に流しています。
引数maxPublishersで並列処理数を制限
大元のpublisherから連続で値が流れてくるような場合は並列でパイプラインが処理されていくので、出力(処理が完了)される数値の順番は1〜5とか限らず処理の早いものから完了していきます。
このような場合に直列に処理をしていきたい場合はmaxPublishers
に.max(並列処理数)
を渡すことで制御することが可能です。例えば以下のように1
を指定すれば1〜5までが順番に出力されていくようにすることができます。
出力結果
Swiftには多次元配列を一次元配列にするためのflatMap
メソッドもありますが、複数のpublisherをフラット(1つのpublisher)にできる点では似ているかもしれません。
異なるエラー型の場合は連結できない
例えば以下のようにAnyPublisher<String, MyError>
とAnyPublisher<String, TestError>
の2つのpublisherを連結したいとします。そのままflatMap
で連結しようとするとコンパイルエラーが発生します。
発生するエラーは以下のとおりです。
エラーが発生しないようにするためにはエラー型を統一させる必要があります。統一させるにはエラー自体を共通のものに置き換えたりするのが綺麗ですがmapError
やcatch
などを使って<String, MyError>
型に合わせてあげればOKです。
エラーがないPublisherは連結可能
エラーがNever
のPublisherの場合は特に気にすることなく連結することが可能です。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。