SwiftUI Firestore Čakať na Načítanie Údajov

0

Otázka

Mám problém pri získavaní Firestore getdocument údajov pred zobrazenie zaťaženia. Viem, že to vracia hodnoty z viacerých kontroly a tam je asi problém s tým, ako zvládam asynchrónne funkcie.

Moje tri premenné, ktoré snažím sa nastaviť.

@Published var numParticipants = 0
@Published var totalAnswered = 0
@Published var showResults = false

Toto je prvá funkcia, ktorá dostane a nastaví počet účastníkov premennej.

func getRoom(roomId: String, onSuccess: @escaping(_ room: Room) -> Void) {
    DB.collection("Rooms").document(roomId).addSnapshotListener { document, error in
        DispatchQueue.main.async {
            if let dict = document?.data() {
                guard let decodeRoom = try? Room.init(fromDictionary: dict) else { return }
                onSuccess(decodeRoom)
            }
        }
    }
}

Táto druhá funkcia, ktorá dostane a stanovuje celkový odpovedal premennej

func getNumParticipants(roomId: String, onSuccess: @escaping(_ numParticipants: Int) -> Void) {

    DB.collection("RoomsParticipants").document(roomId).collection("Participants").getDocuments { snapshot, error in
        DispatchQueue.main.async {
            if let error = error {
                print(error.localizedDescription)
                return
            } else {
                onSuccess(snapshot!.count)
            }
        }
    }
}

A potom som používať tento posledný funkcia porovnať dve premenné a zaťaženie názor, ak sú rovné, inak jednoducho počkajte, kým sú rovnaké.

func checkShowResults(roomId: String) {
    isLoading = true
    
    self.getNumParticipants(roomId: roomId) { numParticipants in
        print("Number of docs: \(numParticipants)")
        DispatchQueue.main.async {
            self.numParticipants = numParticipants
        }
    }
    
    self.getRoom(roomId: roomId) { room in
        print("Total answered: \(room.totalAnswered)")
        DispatchQueue.main.async {
            self.totalAnswered = room.totalAnswered
            if self.totalAnswered == self.numParticipants {
                self.showResults = true
            }
        }
    }
    
    isLoading = false
}

Tu je Results, ktorý sa snažím zobrazenie založené mimo načítané údaje.

struct ResultsView: View {

@StateObject var resultsViewModel = ResultsViewModel()
var roomId: String

var body: some View {
    VStack {
        if !resultsViewModel.showResults {
                VStack {
                    ProgressView()
                    Text("Waiting for all participants \nto finish answering...")
                }
            } else {
                ShowResultsView()
                }
            }
        }
    }.navigationBarHidden(true)
    .onAppear {
        resultsViewModel.checkShowResults(roomId: roomId)
    }
}

Aj v prípade, ak totalAnswered a numParticipants sú rovnaké, ak chcete zobraziť najprv zobrazí, showResults je vždy nastavený na hodnotu false. Ale keď zmeny údajov sa nakoniec dostane nastaviť na hodnotu true, ak sa stanú rovné znova. Myslím, že je to preto, že volanie API na firebase/firestore je čas a premenné nie sú nastavené pred zobrazenie zaťaženia. Nemám naozaj chcete použiť async/čakajú.

1

Najlepšiu odpoveď

2

V súčasnosti svoje kód vykonanie self.getNumParticipants(..) nezávisle od self.getRoom(roomId: roomId). Avšak v checkShowResults, self.getRoom(roomId: roomId)záleží na self.numParticipants aby ste sa dostali z self.getNumParticipants(..). Tak by ste mohli skúsiť hniezdenie vaše funkcie volania. Niečo ako nasledujúci kód:

func checkShowResults(roomId: String) {
    self.isLoading = true
    
    self.getNumParticipants(roomId: roomId) { numParticipants in
        print("Number of docs: \(numParticipants)")
        DispatchQueue.main.async {
            self.numParticipants = numParticipants
            
            // get the room after the numParticipants has been set
            self.getRoom(roomId: roomId) { room in
                print("Total answered: \(room.totalAnswered)")
                DispatchQueue.main.async {
                    self.totalAnswered = room.totalAnswered
                    if self.totalAnswered == self.numParticipants {
                        self.showResults = true
                        self.isLoading = false
                    }
                }
            }
            
        }
    }
2021-11-22 03:36:51

V iných jazykoch

Táto stránka je v iných jazykoch

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................