Decoding nested object with Swift and Firestore

Viewed 388

I’m developing an app with Swift 5 and Firestore. I created structs Identifiables and Codables and it works well but I have problem decoding DocumentID for nested documents. I wasn’t able to find something similar online. I would like to know if Firestore structure I implemented is right in my use case and how to solve id problem.

I have to show a list of activities with just some info about the User and the Sport (like name and image). That's why I'm trying to nest in the Activity object just the info I need to not query the entire User and the Sport for each activity of the list.

On Firestore:

The activity document contains:

info (String)
organizer:
     - name (String)
     - image (String)
     - ref (Reference)
date (Date)
sport:
     - name (String)
     - image (String)
     - ref (Reference)

Here is my code:

import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift

struct User: Codable {
    @DocumentID var id: String? = UUID().uuidString
    
    let name: String
    let email: String?
    let image: String
    let birthday: Date?
    let description: String?
}

struct Sport: Codable {
    @DocumentID var id: String? = UUID().uuidString
    
    let name: String
    let image: String
}

struct Activity: Codable {
    @DocumentID var id: String? = UUID().uuidString
    
    let organizer: User
    let info: String
    let date: Date
    let sport: Sport

    static func getActivities(completion: @escaping (_ activities: [Activity]?) -> Void) {
        Activity.collectionReference.getDocuments { (querySnapshot, error) in
            guard error == nil else {
                print("Error: \(error?.localizedDescription ?? "Generic error")")
                return
            }
            
            let activities = querySnapshot?.documents.compactMap({ (queryDocumentSnapshot) -> Activity? in
                
                return try! queryDocumentSnapshot.data(as: Activity.self)
            })
            
            completion(activities)
        }
    }
}

Calling Activity.getActivities I'm able to get everything I need but decoding the user and sport directly from activity object they get the activity ID instead of their own. That's wrong because in this way I have the wrong reference to the object. The idea is to keep the reference to use it in the details page and fetching the complete object. Can someone told me what's the best way to structure this kind of architecture? Thank you in advance.

0 Answers
Related