Learn Courses My Dashboard

Displaying Firestore Data in a View

Hello, I am learning Swift, SwiftUI and Firestore. I am having trouble displaying the data from Firestore into a my view the way I want it to. My goal is to display a list of flavor groups, along with a list of associated descriptor words for each flavor group. Here is an example of the list I am trying to accomplish in a view:

APRICOT
• FRUITY
BLACK WALNUT
• FATTY
CASHEW
CHESTNUT
CITRUS
• GRAPEFRUIT
• LEMON
• ORANGE

My Firestore database is setup as follows:

Collections - One collection named “flavors”
Documents - Multiple documents with auto UUID names
Fields (identical for each document):
• code (string)
• descriptors (array of strings)
• flavorGroup (string)
• keywords (array of strings)
• legislation (string)
• name (string)

The 2 Firestore fields that I want to display data from are flavorGroup and descriptors. Example:

flavorGroup
• descriptor
flavorGroup
• descriptor
flavorGroup
flavorGroup
flavorGroup
• descriptor
• descriptor
• descriptor

Notice that for some Firebase documents, the descriptor array is empty.

I am able to successfully read data from the database and display it in a view, just not in formated as in the list above.

Here is the model code I am using in a file named Flavor.swift:

    struct Flavor: Identifiable, Codable {
        @DocumentID var id: String? = UUID().uuidString
         var code: String
         var descriptors: [String]
         var flavorGroup: String
         var keywords: [String]
         var legislation: String\
         var name: String
    }

Here is the view model code I am using in a file named FlavorsViewModel.swift:

    class FlavorsViewModel: ObservableObject {
        @Published var flavors = [Flavor]()
        private var db = Firestore.firestore()
        func fetchData() {
            db.collection("flavors").addSnapshotListener { (querySnapshot, error) in
                guard let documents = querySnapshot?.documents else {
                    print("No documents")
                    return
                }
                self.flavors = documents.compactMap { (queryDocumentSnapshot) -> Flavor? in
                    return try? queryDocumentSnapshot.data(as: Flavor.self)
                }
            }
        }
    }

Now, in my view file I am only able to successfully list by flavor group using this code:

    struct FlavorsListView: View {
        @ObservedObject private var viewModel = FlavorsViewModel()
        var body: some View {
            NavigationView {
                List(viewModel.flavors) { flavorListing in
                    VStack(alignment: .leading) {
                        Text("Flavor Group: \(flavorListing.flavorGroup)")
                            .font(.subheadline)
                    }
                }
                .navigationBarTitle("Flavors")
                .onAppear() {
                    self.viewModel.fetchData()
                }
            }
        }
    }

This allows me to display flavorGroup field in a list but not the descriptor array below each flavorGroup in the list. How can I display the descriptor array also? Any help at all will be most appreciated. Thank you.

Solution found. Here is the updated view code:

    struct FlavorsListView: View {
        @ObservedObject private var viewModel = FlavorsViewModel()
        var body: some View {
            NavigationView {
                List(viewModel.flavors) { flavorListing in
                    VStack(alignment: .leading) {
                        Text("Flavor Group: \(flavorListing.flavorGroup)")
                            .font(.subheadline)
                    }
                    VStack(alignment: .leading)  {
                                ForEach(flavorListing.descriptors, id: \.self) { descriptor in
                                    Text("- \(descriptor)")
                                    .padding(.vertical, 1.0)
                                }
                         }
                }
                .navigationBarTitle("Flavors")
                .onAppear() {
                    self.viewModel.fetchData()
                }
            }
        }
    }