【问题标题】:SwiftUI Firestore Wait for Loading DataSwiftUI Firestore 等待加载数据
【发布时间】:2021-12-31 17:12:40
【问题描述】:

在加载视图之前检索 Firestore getdocument 数据时遇到问题。我知道它会从多个检查中返回值,并且我处理异步函数的方式可能存在问题。

我正在尝试设置的三个变量。

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

这是第一个获取和设置参与者数量变量的函数。

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

这是获取和设置总回答变量的第二个函数

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

然后我使用最后一个函数来比较两个变量,如果它们相等则加载视图,否则就等到它们相等。

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
}

这是我尝试根据获取的数据显示的结果视图。

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

即使在最初显示视图时 totalAnswered 和 numParticipants 相等,showResults 也始终设置为 false。但是当数据发生变化时,如果它们再次相等,它最终会被设置为 true。我认为这是因为对 firebase/firestore 的 API 调用需要时间,并且在视图加载之前未设置变量。我真的不想使用 async/await。

【问题讨论】:

  • 当前您的代码执行self.getNumParticipants(..) 独立于self.getRoom(roomId: roomId)。但是在checkShowResults 中,self.getRoom(roomId: roomId) 取决于您从self.getNumParticipants(..) 获得的self.numParticipants。所以你可以尝试嵌套你的函数调用。也就是说,在设置了self.numParticipants 之后,将self.getRoom(roomId: roomId) 放在self.getNumParticipants(roomId: roomId) 中。此外,我会将isLoading = false 放在self.showResults = true 之后的self.getRoom(roomId: roomId) 中。
  • 谢谢@workingdog 工作得很好。
  • 好,我已经用这种方法发布了答案。

标签: xcode asynchronous google-cloud-firestore swiftui async-await


【解决方案1】:

目前您的代码独立于self.getRoom(roomId: roomId) 执行self.getNumParticipants(..)。 然而在checkShowResultsself.getRoom(roomId: roomId) 取决于 在您从self.getNumParticipants(..) 获得的self.numParticipants 上。 所以你可以尝试嵌套你的函数调用。类似于以下代码:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 2021-09-08
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多