SwiftUİ Firestore Veri Yüklenmesini Bekleyin

0

Soru

Görünüm yüklenmeden önce Firestore getdocument verilerini almakta sorun yaşıyorum. Birden çok denetimden değerler döndürdüğünü biliyorum ve muhtemelen eşzamansız işlevleri nasıl ele aldığımla ilgili bir sorun var.

Belirlemeye çalıştığım üç değişkenim.

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

Bu, katılımcı sayısı değişkenini alan ve ayarlayan ilk işlevdir.

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)
            }
        }
    }
}

Bu, toplam yanıtlanan değişkeni alan ve ayarlayan ikinci işlevdir

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)
            }
        }
    }
}

Ve sonra bu son işlevi iki değişkeni karşılaştırmak ve eşitse görünümü yüklemek için kullanıyorum, aksi halde eşit olana kadar bekleyin.

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
}

İşte getirilen verilere dayanarak görüntülemeye çalıştığım Sonuç Görünümü.

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)
    }
}

Görünüm başlangıçta görüntülendiğinde totalAnswered ve numParticipants eşit olsa bile, showResults her zaman false olarak ayarlanır. Ancak veriler değiştiğinde, tekrar eşit olurlarsa sonunda true olarak ayarlanır. Bunun nedeni, firebase/firestore'a yapılan API çağrısının zaman alması ve görünüm yüklenmeden önce değişkenlerin ayarlanmamasıdır. Gerçekten async / await kullanmak istemiyorum.

1

En iyi cevabı

2

Şu anda kodunuz yürütülüyor self.getNumParticipants(..) bağımsız olarak self.getRoom(roomId: roomId). Ancak içinde checkShowResults, self.getRoom(roomId: roomId) bağlı olmak üzerinde self.numParticipants bundan aldığın self.getNumParticipants(..). Böylece işlev çağrılarınızı yuvalamayı deneyebilirsiniz. Aşağıdaki kod gibi bir şey:

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

Diğer dillerde

Bu sayfa diğer dillerde

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