1

I'm trying to load data into a SwiftUI view using Firebase/Firestore. The data loads from the database but doesn't get passed into the view.

I know it loads because I print it once it has loaded.

I have a HomeView.Swift file as follows:

import SwiftUI
import Firebase

struct HomeView: View {
    let data = GetIphonesData()
    var body: some View {
        NavigationView {
            if (data.data.count == 0) {
                Loader()
                .navigationBarTitle("Loading", displayMode: .inline)
            } else {
                List() {
                    Section(header: Text("iPhone")) {
                        ForEach(data.data , id: \.id) { iphone in
                            ProductNavigationLinkView(model: iphone)
                        }
                    }
                }.listStyle(GroupedListStyle())
                .navigationBarTitle("Home", displayMode: .inline)
            }
        }
    }
}

And I have a GetIphoneData.Swift class as follows:

import Foundation
import Firebase
import Combine

class GetIphonesData : ObservableObject {
    @Published var data = [Iphone]()

    init() {
        let db = Firestore.firestore()

        db.collection("iphones").addSnapshotListener { (snap, err) in
            if err != nil {
                print((err?.localizedDescription)!)
                return
            } else {
                print("no errors")
                for i in snap!.documentChanges {
                    let id = i.document.documentID
                    let name = i.document.get("name") as! String

                    self.data.append(Iphone(id: id,
                                            name: name))
                }
                print(self.data)
            }
        }
    }
}

1 Answers1

1
  1. SwiftUI updates its View's content on a main thread. Wrap your closure content of addSnapshotListener into Dispatch.main.async.
db.collection("iphones").addSnapshotListener { (snap, err) in
  DispatchQueue.main.async {
    if err != nil {
        print((err?.localizedDescription)!)
        return
    } else {
        print("no errors")
        for i in snap!.documentChanges {
            let id = i.document.documentID
            let name = i.document.get("name") as! String

            self.data.append(Iphone(id: id,
                                    name: name))
        }
        print(self.data)
    }
  }
}
  1. Also your let data = GetIphonesData() should have @ObservedObject property wrapper:
struct HomeView: View {
    @ObservedObject var data = GetIphonesData()
    // ...
  1. Please see this answer as a reference of using @ObservedObject and @Published
Aleksey Potapov
  • 3,683
  • 5
  • 42
  • 65