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

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

この記事からわかること

  • SwiftCombineフレームワーク
  • catchメソッド使い方
  • エラーごとに処理分岐する方法

index

[open]

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

みんなの誕生日

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

posted withアプリーチ

公式リファレンス:Combine Framework

環境

catchメソッドの使い方

公式リファレンス: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 マッピング中にエラーを投げられる処理を実行する エラー処理をマッピングと統合したい場合

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

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

searchbox

スポンサー

ProFile

ame

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

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

New Article

index