繁体   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