![](/img/trans.png)
[英]Swift - Problem While Downloading Data From Firebase Firestore Asynchronously with DispatchGroup()
[英]Pausing while downloading Firestore data
我正在使用Google Firestore為我的應用程序的用戶存儲數據。 應用加載后,如果用戶已登錄,我想獲取他們的數據。 我需要訪問三個不同的文檔,因此我創建了一個Loading視圖控制器,它調用如下三個函數:
override func viewDidLoad() {
super.viewDidLoad()
loadingFunction1()
loadingFucntion2()
loadingFunction3()
...
self.performSegue(withIdentifier: "goToNextScreen", sender: nil)
}
每個函數看起來都像這樣:
func loadingFunction1() {
self.database.collection("doc").getDocuments() { (querySnapshot, error) in
...get document from Firestore and store it locally
}
}
我需要先加載所有數據,然后segue才能將應用程序帶到下一個屏幕。
我努力了:
我遵循了Ray Wenderlich的DispatchGroups教程( https://www.raywenderlich.com/148515/grand-central-dispatch-tutorial-swift-3-part-2 )
我已經試過這個Stack Overflow問題( iOS-swift 3-DispatchGroup )
我已閱讀DispatchGroup在Swift 3中不起作用, 如何使用DispatchGroup / GCD在swift中按順序執行功能? 以及如何使用完成處理程序來等待Firestore請求的完成,我仍然感到困惑。
在繼續下一步操作之前,如何使我的應用完全執行這三個功能。 我什至不在乎這三個功能的執行順序,只要在繼續進行之前將它們完全完成即可。
順便說一句,我的ViewController有一個非常漂亮的動畫“活動指示器視圖”,可以在發生這種情況時娛樂用戶。
解決方案更新:
我采用了一系列的Bools建議,並在注釋中使用了didSet的想法:
var completedRequests: [Bool] = [false, false, false] {
didSet {
segueWhenAllRequestsAreComplete()
}
}
但是,這還不夠。 我必須向每個函數添加轉義完成處理程序和dispatchGroup,如下所示:
func loadingFunction1(completion: @escaping (Bool) -> ()) {
DispatchQueue.global(qos: .userInteractive).async {
let downloadGroup = DispatchGroup()
var success:Bool = false
downloadGroup.enter()
self.database.collection("doc").getDocuments() { (querySnapshot, error) in
if error == nil {
...get document from Firestore and store it locally
success = true
}
downloadGroup.leave()
}
downloadGroup.wait()
DispatchQueue.main.async {
completion(success)
}
}
}
然后調用如下函數:
DataManager.shared.loadData { success in
self.completedRequests[0] = success
}
因此,現在,直到全部三個功能都完成后,segue才會啟動。 似乎有一些回合,但它可行。
您可以嘗試像這樣嵌套通話
func loadingFunction1() {
self.database.collection("doc").getDocuments() { (querySnapshot, error) in
// ...get document from Firestore and store it locally
self.loadingFunction2()
}
}
直到3
func loadingFunction3() {
self.database.collection("doc").getDocuments() { (querySnapshot, error) in
// ...get document from Firestore and store it locally
self.performSegue(withIdentifier: "goToNextScreen", sender: nil)
}
}
嵌套調用將使它們按順序進行,這不是很有效,將需要更長的時間才能完成。 一種更快的方法是使它們像現在一樣並發運行,並在每個完成時檢查是否最后一個要完成。
首先,將一系列待處理的請求以及一種檢查請求是否已完成的方法添加到視圖控制器:
var completedRequests: [Bool] = [false, false, false]
func segueWhenAllRequestsCompleted() {
if !completedRequests.contains(false) {
performSegue(withIdentifier: "goToNextScreen", sender: nil)
}
}
然后,在每個加載函數中:
func loadingFunction1() {
completedRequests[0] = false
self.database.collection("doc").getDocuments() { (querySnapshot, error) in
...get document from Firestore and store it locally
self.completedRequests[0] = true
self.segueWhenAllRequestsCompleted()
}
}
func loadingFunction2() {
completedRequests[1] = false
self.database.collection("doc").getDocuments() { (querySnapshot, error) in
...get document from Firestore and store it locally
self.completedRequests[1] = true
self.segueWhenAllRequestsCompleted()
}
}
func loadingFunction3() {
completedRequests[2] = false
self.database.collection("doc").getDocuments() { (querySnapshot, error) in
...get document from Firestore and store it locally
self.completedRequests[2] = true
self.segueWhenAllRequestsCompleted()
}
}
這樣,您的視圖控制器將在所有請求完成后自動選擇並繼續運行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.