Vitalyz123
Vitalyz123

Reputation: 209

RxSwift Combine Array of observables with array of objects

I'm trying to fetch data from Firebase using RxSwift. I'm using this to perform API calls.

So my db looks like this: Collection Category (it has properties: title, about etc) has inside of it another collection called Manifests. To get Manifests I need to use documentId of Category collection. So it's two different API calls but I want to combine results

That is what I have so far:

    func fetchCategories() -> Observable<[ManifestCategory]> {
        let ref = self.db.collection(FirebaseCollection.manifestCategories.collectionPath)

        return ref.rx.getDocuments().map({ snapshot in
            return snapshot.documents.map({ doc in
                var category = ManifestCategory.init(JSON: doc.data())

                category?.documentId = doc.documentID

                return category
                }).compactMap({ $0 })
        })
    }

    func fetchManifests(categoryId: String) -> Observable<[Manifest]> {
        let ref = self.db.collection(FirebaseCollection.manifests(categoryId: categoryId).collectionPath)

        return ref.rx.getDocuments().map({ snapshot in
            return snapshot.documents.map({ doc in
                var manifest = Manifest.init(JSON: doc.data())

                manifest?.documentId = doc.documentID

                return manifest
            }).compactMap({ $0 })
        })
    }

Is there any way I can put Manifests array into Category object?

Thank you!

Upvotes: 0

Views: 1097

Answers (1)

hell0friend
hell0friend

Reputation: 569

You should try something like this:

func fetchCategories() -> Observable<[ManifestCategory]> {
    let ref = self.db.collection(FirebaseCollection.manifestCategories.collectionPath)

    return ref.rx.getDocuments()
        .map { snapshot in
            return snapshot.documents
                .map { doc in
                    var category = ManifestCategory.init(JSON: doc.data())
                    category?.documentId = doc.documentID
                    return category
                }
                .compactMap { $0 }
        }
        .flatMapLatest { [weak self] categories -> Observable<[ManifestCategory]> in
            guard let self = self else {
                return .empty()
            }

            let observables = categories.map { category -> ([Manifest], String) in
                self.fetchManifests(categoryId: category.documentId)
                    .map { ($0, category.documentId) }
            }

            return Observable.zip(observables)
                .map { tuple -> [ManifestCategory] in
                    tuple.compactMap { manifests, id in
                        if var category = categories.first(where: { $0.documentId == id }) {
                            category.manifests = manifests
                            return category
                        }
                        return nil
                    }
                }
        }
}

Upvotes: 1

Related Questions