GCD 未按块顺序执行
GCD Not Executing In Block Order
我正在尝试从我的 Firebase 数据库中检查某些节点是否存在,如果不存在,则在数据库中创建新节点。我需要我的方法 loadAll()
在它调用创建任何缺失节点的第二个方法 autoCheck
之前完全执行。我尝试了一个调度组来执行此操作,但它不起作用,print("Done downloading!")
在完成检查数据库之前被调用。谢谢!!
代码:
func loadAll(){
var deleted_load = false
var poor_load = false
var allLoadDone = false
if let user = FIRAuth.auth()?.currentUser {
let uid = user.uid
let refff = FIRDatabase.database().reference()
let userRef = refff.childByAppendingPath("users/\(uid)")
//When making new fields increase this var
var howmany = 2
var done = 0
var downloadGroup = dispatch_group_create()
dispatch_group_enter(downloadGroup)
userRef.queryOrderedByValue().observeEventType(.ChildAdded, withBlock: { snapshot in
allLoadDone = true
if(!snapshot.exists()){
print("ERR DOES NOT EXCIST")
self.autoCheck(deleted_load, poor_load: poor_load, userRef: userRef, ig: 1)
return
}
if let score = snapshot.value as? Int {
if(snapshot.key=="deleted"){
deleted_load = true
}
if(snapshot.key=="Staff_Poor"){
poor_load = true
}
print("\(snapshot.key) is \(score)")
self.counter.text = String(score)
}
done = done + 1
if(done>=(howmany)){
self.autoCheck(deleted_load, poor_load: poor_load, userRef: userRef, ig: 2)
}
})
dispatch_group_leave(downloadGroup)
dispatch_group_notify(downloadGroup, dispatch_get_main_queue()) { // 2
print("Done downloading!")
}
} else {
print("No user!")
gotoLogin()
}
}
func autoCheck(deleted_load: Bool, poor_load: Bool, userRef: FIRDatabaseReference, ig: Int) -> Bool{
print("ID IS: \(ig)")
var newUserData = ["deleted": 0, "Staff_Poor": 0]
print("deleted_load: \(deleted_load)")
if deleted_load==true{
newUserData.removeValueForKey("deleted")
}
print("poor_load: \(poor_load)")
if poor_load==true{
newUserData.removeValueForKey("Staff_Poor")
}
if(!newUserData.isEmpty){
userRef.updateChildValues(newUserData)
}
return true
}
您对 dispatch_group_leave(downloadGroup)
的调用必须放在完成处理程序闭包中。现在,你把它放在外面,这意味着该组将在异步调用完成之前完成。
但让我们退后一步,了解调度组的用途。典型的模式是在执行一系列异步任务时使用调度组,并且您想知道它们何时完成。因此,对于每个任务,您在调用某个异步过程之前进入该组,然后将该组留在该异步过程的完成处理程序中,例如:
let group = dispatch_group_create()
for object in arrayOfObjects {
dispatch_group_enter(group)
performSomeAsynchronousActionWithObject(object) { result in
// do something with `result`
...
dispatch_group_leave(group)
}
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done performing asynchronous task with all of those objects")
}
坦率地说,在这里使用调度组可能不合适。调度组的概念是每个 "enter" 都与相应的 "leave" 相匹配。您正在调用 "enter" 一次,但不清楚您能否保证观察者最终会被调用多少次。
但在这种情况下,您处理的是 "observer" 一些将被调用的代码块,无论事件发生了多少次。它可能根本不会发生。它可能会发生很多次。这只是观察到的事件发生了多少次的问题。
现在,如果您确定这将被调用一次且仅调用一次,那么从技术上讲,这种模式是可行的。但是如果它只被调用一次,那么你根本不需要调度组。
我正在尝试从我的 Firebase 数据库中检查某些节点是否存在,如果不存在,则在数据库中创建新节点。我需要我的方法 loadAll()
在它调用创建任何缺失节点的第二个方法 autoCheck
之前完全执行。我尝试了一个调度组来执行此操作,但它不起作用,print("Done downloading!")
在完成检查数据库之前被调用。谢谢!!
代码:
func loadAll(){
var deleted_load = false
var poor_load = false
var allLoadDone = false
if let user = FIRAuth.auth()?.currentUser {
let uid = user.uid
let refff = FIRDatabase.database().reference()
let userRef = refff.childByAppendingPath("users/\(uid)")
//When making new fields increase this var
var howmany = 2
var done = 0
var downloadGroup = dispatch_group_create()
dispatch_group_enter(downloadGroup)
userRef.queryOrderedByValue().observeEventType(.ChildAdded, withBlock: { snapshot in
allLoadDone = true
if(!snapshot.exists()){
print("ERR DOES NOT EXCIST")
self.autoCheck(deleted_load, poor_load: poor_load, userRef: userRef, ig: 1)
return
}
if let score = snapshot.value as? Int {
if(snapshot.key=="deleted"){
deleted_load = true
}
if(snapshot.key=="Staff_Poor"){
poor_load = true
}
print("\(snapshot.key) is \(score)")
self.counter.text = String(score)
}
done = done + 1
if(done>=(howmany)){
self.autoCheck(deleted_load, poor_load: poor_load, userRef: userRef, ig: 2)
}
})
dispatch_group_leave(downloadGroup)
dispatch_group_notify(downloadGroup, dispatch_get_main_queue()) { // 2
print("Done downloading!")
}
} else {
print("No user!")
gotoLogin()
}
}
func autoCheck(deleted_load: Bool, poor_load: Bool, userRef: FIRDatabaseReference, ig: Int) -> Bool{
print("ID IS: \(ig)")
var newUserData = ["deleted": 0, "Staff_Poor": 0]
print("deleted_load: \(deleted_load)")
if deleted_load==true{
newUserData.removeValueForKey("deleted")
}
print("poor_load: \(poor_load)")
if poor_load==true{
newUserData.removeValueForKey("Staff_Poor")
}
if(!newUserData.isEmpty){
userRef.updateChildValues(newUserData)
}
return true
}
您对 dispatch_group_leave(downloadGroup)
的调用必须放在完成处理程序闭包中。现在,你把它放在外面,这意味着该组将在异步调用完成之前完成。
但让我们退后一步,了解调度组的用途。典型的模式是在执行一系列异步任务时使用调度组,并且您想知道它们何时完成。因此,对于每个任务,您在调用某个异步过程之前进入该组,然后将该组留在该异步过程的完成处理程序中,例如:
let group = dispatch_group_create()
for object in arrayOfObjects {
dispatch_group_enter(group)
performSomeAsynchronousActionWithObject(object) { result in
// do something with `result`
...
dispatch_group_leave(group)
}
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done performing asynchronous task with all of those objects")
}
坦率地说,在这里使用调度组可能不合适。调度组的概念是每个 "enter" 都与相应的 "leave" 相匹配。您正在调用 "enter" 一次,但不清楚您能否保证观察者最终会被调用多少次。
但在这种情况下,您处理的是 "observer" 一些将被调用的代码块,无论事件发生了多少次。它可能根本不会发生。它可能会发生很多次。这只是观察到的事件发生了多少次的问题。
现在,如果您确定这将被调用一次且仅调用一次,那么从技术上讲,这种模式是可行的。但是如果它只被调用一次,那么你根本不需要调度组。