【发布时间】:2018-03-21 22:18:13
【问题描述】:
我正在使用 Google Firestore 为我的应用用户存储数据。当应用程序加载时,如果用户登录,我想获取他们的数据。我需要访问三个不同的文档,所以我创建了一个 Loading viewController,它调用三个函数,如下所示:
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,而是在包含三个函数的类中的每个函数中完成了它。在完成之前仍然会触发 segue。
我已关注 Ray Wenderlich 的 DispatchGroups 教程 (https://www.raywenderlich.com/148515/grand-central-dispatch-tutorial-swift-3-part-2)
我试过这个 Stack Overflow 问题 (iOS - swift 3 - DispatchGroup)
我已经阅读了DispatchGroup not working in Swift 3 和 How do I use DispatchGroup / GCD to execute functions sequentially in swift? 和 how to use a completion handler to await the completion of a firestore request ,但我仍然很难过。
如何让我的应用在执行下一个操作之前完全执行这三个功能中的每一个。我什至不在乎这三个功能的执行顺序是什么,只要它们在继续之前完全完成即可。
顺便说一句,我的 ViewController 有一个非常漂亮的动画活动指示器视图,可以在这一切发生时娱乐用户。
更新解决方案:
我采用了 Bools 数组的建议,以及来自 cmets 的 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 不会触发。看起来有点绕,但确实有效。
【问题讨论】:
标签: ios swift grand-central-dispatch google-cloud-firestore completionhandler