【Swift/Combine】catchメソッドの使い方!エラーを補足する方法

この記事からわかること
- SwiftのCombineフレームワーク
- catchメソッドの使い方
- エラーごとに処理を分岐する方法
index
[open]
\ アプリをリリースしました /
環境
- Xcode:15.0.1
- iOS:17.1
- Swift:5.9
- macOS:Sonoma 14.1
catchメソッドの使い方
func `catch`<P>(_ handler: @escaping (Self.Failure) -> P) -> Publishers.Catch<Self, P> where P : Publisher, Self.Output == P.Output
SwiftのCombineフレームワークのcatch
はエラーを補足し別のpublisherを流すメソッドです。catch
を使用することで特定のエラーの場合は代替のストリームを提供し、特定のエラーの場合はそのままエラーを流すといったことができるようになります。
完了ハンドラーのクロージャーの引数から流れてくるerror
を参照することができ、最終的にpublisher
を返します。
let publisher = PassthroughSubject<Int, MyError>()
let subscription = publisher
.catch { error in
// エラーが発生するとここが呼ばれる
// クロージャーの引数から対象errorを参照できる
// 後続のストリームに流すpublisherを返す
Just(0)
}
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("完了")
case .failure(let error):
print("Error:", error)
}
}, receiveValue: { value in
print("Value:", value)
})
// パブリッシャーから値を送信
publisher.send(10)
publisher.send(completion: .failure(NSError(domain: "", code: 0, userInfo: nil)))
例えば上記のように実装した場合エラーが発生した場合はJust(0)
を代わにストリームに流すため以下のような出力になります。
Value: 10
Value: 0
完了
エラーの値によって後続に流すストリームを分岐させる
「Aエラーならそのまま、Bエラーなら別のpublisherを流したい」場合などエラーの値によって後続に流すストリームを分岐させるには以下のように実装すればOKです。
let publisher = PassthroughSubject<Int, MyError>()
enum MyError: Error {
case someError1
case someError2
}
let subscription = publisher
.catch { error -> AnyPublisher<Int, MyError> in
switch error {
case .someError1:
// エラーをそのまま返す
return Fail(error: error).eraseToAnyPublisher()
case .someError2:
// 代替の値を返す
return Just(0).setFailureType(to: MyError.self).eraseToAnyPublisher()
}
}
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("完了")
case .failure(let error):
print("Error:", error)
}
}, receiveValue: { value in
print("Value:", value)
})
// パブリッシャーから値を送信
publisher.send(10)
publisher.send(completion: .failure(.someError1))
その他のエラーハンドリングメソッド
オペレーター | 説明 | 使用場面 |
---|---|---|
replaceError | エラーを無視してデフォルト値を流す | エラーを無視して安全に値を流したい場合 |
catch | エラーが発生した際に代わりのPublisherを流す | エラーごとに異なる処理をしたい場合 |
mapError | エラーを別のエラー型に変換する | エラー型を統一したい場合 |
retry | エラーが発生した場合に処理を再試行する | 再試行可能な操作を扱いたい場合 |
tryMap | マッピング中にエラーを投げられる処理を実行する | エラー処理をマッピングと統合したい場合 |
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。