iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

【RxSwift】Observableを再帰的に実行したい

Observableを再帰的に実行するサンプル実装をしたので、軽くメモしておきます👀 もっといい書き方あったらコメントで教えてください!

どんな状況?

やりたいこととしては、データIDの配列からページネーションしながらIDを取り出し、そのIDを元にデータを取得するという実装です。この時に問題となっているのが、データID配列の中に取得できない(取得しようとした際にエラーとなる)データが含まれていることです。つまり、エラーが発生した場合は、ページに含まれるデータの数が少なくなってしまうので、再帰的に次のIDからデータを取得してくる必要があります。

そしてできたのが、下記のような実装。再帰実行したいObservableをローカル関数として実装することで、再帰的なObservableを生成することができます。これにより、Errorが発生した場合でも、データを指定した数、再帰的に取得することができるようになります。

    private func get() -> Single<[Data]> {
        var currentItems: [Data] = []
        return Single.create {[unowned self] observer in
            @discardableResult
            func addDataIfNeed() -> Disposable {
                guard let id = currentData.popularProductIds[safe: pageData.currentIndex] else {
                    observer(.success(currentItems))
                    return Disposables.create()
                }
                return repository.get(id: id)
                    .catchErrorJustReturn(nil)
                    .subscribe(onSuccess: { data in
                        if (pageData.currentIndex - 1) >= pageData.ids.count || currentItems.count == perPage {
                            observer(.success(currentItems))
                        } else {
                            pageData.currentIndex += 1
                            if let data = data {
                                currentItems.append(data)
                            }
                            addDataIfNeed()
                        }
                    })
            }
            return addDataNeed()
        }
    }

@discardableResult属性については下記を参照してみてください。

yamatooo.blog

てな感じで本日も以上となります🍺

その他の記事

yamatooo.blog

yamatooo.blog

yamatooo.blog