【Swift/Combine】catchメソッドの使い方!エラーを補足する方法
この記事からわかること
- SwiftのCombineフレームワーク
- catchメソッドの使い方
- エラーごとに処理を分岐する方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- 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))
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。