[英]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.