我有一系列的ViewControllers
,每个都将数据上传到Firebase
。我想知道是否可以创建一个串行队列,以确保它们按照显示视图控制器的顺序进行上传。我是否需要创建一个委托方法来执行类似的操作?
我的ViewController
如下所示
VC 1:
class VC1: UIViewController{
func nextVC(_ data: Data){
db.collection("collection")
.document("Document").setData([
"data1": data
]){ err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
self.performSegue(withIdentifier: K.firstSegue, sender: self)
}
}
VC 2:
class VC2: UIViewController{
func nextVC(_ data: Data){
db.collection("collection")
.document("Document").updateData([
"data2": data
]){ err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
self.performSegue(withIdentifier: K.secondSegue, sender: self)
}
}
VC 3:
class VC3: UIViewController{
func nextVC(_ data: Data){
db.collection("collection")
.document("Document").updateData([
"data3": data
]){ err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
}
}
编辑:进行澄清
我遇到的问题是,当我到达第三个视图控制器时,我会得到一个错误,即我尝试更新的文档不存在。我认为,通过将所有三个Firebase
调用添加到DispatchQueue
中,可以避免此问题。这确实奏效,但是我在视图控制器之间的滞后时间遇到了问题。我希望ViewControllers
将他们的数据添加到队列中,以串行方式上传到Firebase
,以便他们按正确的顺序加载,并在后台进行,以便它不会影响用户界面。
答案 0 :(得分:3)
Firebase任务本身是异步的,因此创建队列除了保证按顺序启动外,不能保证其他任何事情。但这仅是从主线程启动它们而已。而且,您不能保证会按顺序收到或按顺序完成它们。
如果确实必须按顺序运行这些命令,则必须在先前请求的完成处理程序中移动segue的启动。例如,考虑:
func nextVC(_ data: Data){
db.collection("collection").document("Document").setData(["data1": data]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
}
}
self.performSegue(withIdentifier: K.firstSegue, sender: self)
}
将其更改为
func nextVC(_ data: Data){
db.collection("collection").document("Document").setData(["data1": data]) { err in
if let err = err {
print("Error writing document: \(err)")
} else {
print("Document successfully written!")
self.performSegue(withIdentifier: K.firstSegue, sender: self)
}
}
}
还有其他模式(异步自定义Operation
子类,合并等),但这是最简单的方法。
答案 1 :(得分:2)
就单个串行队列问题而言,只需说出您通常会说的话即可,即
let queue = DispatchQueue(label:"myqueue")
...但是在正确的地方说出 。为什么地方很重要?因为在Swift中,位置决定了寿命和范围。您想要一个所有其他代码都可以看到的队列(全局范围),该队列将一直存在(生存期)。
有两种主要方法可以做到这一点。一种是说声明在任何类声明之外。例如,将其放在import
语句之后的 AppDelegate.swift 文件的顶部。这使它成为纯全局。在您的应用程序代码中到处都有简单的名称。
另一种方法是使它成为某个类或其他类型的static let
。这赋予它全局范围,同时也很好地命名它。例如:
struct GlobalQueues { // or this could be an enum
static let firebaseQueue = DispatchQueue(label:"myqueue")
}
结果是您可以在应用程序代码中的任何地方引用GlobalQueues.firebaseQueue
,这比纯全局名称更好。它没有功能上的区别,但它阐明了这个东西是什么以及它的“住处”。
答案 2 :(得分:0)
我找到了解决问题的方法。由于我在更新文档时遇到很多错误,因此我决定一次上传所有信息,方法是将所有必需的信息传递到最后一个vc并上传。