簡體   English   中英

下載Firestore數據時暫停

[英]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才能將應用程序帶到下一個屏幕。

我努力了:

  • 每個函數的完成處理程序-它們各自以正確的順序執行,但是segue在它們全部完成之前就會觸發。
  • 嵌套完成處理程序-將每個函數放在先前功能的完成處理程序中,仍然會在完成之前觸發segue。
  • 將所有三個函數調用放入DispatchGroup中,仍會在完成之前觸發。
  • 我沒有在ViewController中執行DispatchGroup / Queue事情,而是在包含三個函數的類的每個函數中完成了它。 在完成之前,仍然會開火。

我遵循了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM