LoginSignup
3
4

More than 3 years have passed since last update.

CombineによるPublisherの受け渡し

Last updated at Posted at 2020-03-24

はじめに

RxSwiftを利用したVIPERアーキテクチャのソースコードをcombineで書き直している。
RxSwiftでは、InteractorがAPIから非同期処理で取得したデータをPresenterに渡す際、Singleオブジェクトとして扱っていた。SingleだったところをcombineではFutureオブジェクトにしたのだが、両者はGenericsの型の数が異なる。直接参考になるソースを見つけられなかったため我流のものだが書き残しておく。ただ、もっと良い方法があると思われるので、詳しい方にご教示いただきたいというのが正直なところである。

ソースコード

fetchFutureOnPresenter(flag: Bool)trueを入れればStringIntに変換された値が返ってくる。falseにすればPresenterを経由せずにエラーが投げられることをplaygroundで動作確認をした。


struct APIError: Error {
    var description: String
}

// InteractorがAPIにアクセスしてレスポンスを取得する想定
func fetchFutureOnInteractor(flag: Bool) -> AnyPublisher<String, Error> {

    return Future<String, Error>{ promise in

        ///
        /// 実際はここに非同期処理を書く想定
        ///

        // 非同期処理の結果によって、場合分け
        if flag {
            promise(.success("0"))
        } else {
            promise(.failure(APIError(description: "☓")))
        }
    }
    .eraseToAnyPublisher()
}

// PresenterがInteractorのメソッドから取得したデータをViewに渡す用に変換する想定
// flatMapでAnyPublisher<String, Error>からAnyPublisher<Int, Error>に変換
func fetchFutureOnPresenter(flag: Bool) -> AnyPublisher<Int, Error> {
    return fetchFutureOnInteractor(flag: flag)
        .flatMap { output -> AnyPublisher<Int, Error> in // クロージャの戻り値をIntにする
            Future<Int, Error>{ promise in
                promise(.success(Int(output)!))          // Intにキャスト、エラー(Failure)は、ここでは記載しない
            }
            .eraseToAnyPublisher()
    }
    .eraseToAnyPublisher()
}

// Presenterが購読(.sink)
let cancellable = fetchFutureOnPresenter(flag: /* true or false */)
.sink(receiveCompletion: { completion in
        switch completion {
        case .finished:
            break
        case .failure(let error):
            // Interactorの.failureはここに投げられる
            print("error \(error)")
        }
    }, receiveValue: { value in
        // このvalueを元にViewが参照する値を更新する想定
        print("value \(value)")
    })
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4