调度组:for循环*和*for循环内的异步调用
dispatch group: for-loop *and* async calls within the for-loop
我了解如何在简单的 for 循环中使用调度组。但是,我有一个更复杂的 for 循环,其中包含更多异步调用 。我希望在执行组完成代码之前完成所有异步调用。我试图应用此答案中的原则无济于事- 。这是我的代码,基于我在 link:
中观察到的技术
let group = DispatchGroup()
for ref in self.notifsRefList {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { notifRecord, notifErr in
print("async call")
if notifErr == nil {
// do stuff
if let ref = notifRecord?.object(forKey: POST) as! CKReference? {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { postRecord, err in
print("async call")
if err == nil {
// do stuff
group.leave()
}
else {
print("\(err)")
group.leave()
}
}
}
if let ref = notifRecord?.object(forKey: USER_NOTIF) as! CKReference? {
self.db.fetch(withRecordID: ref.recordID) { userRecord, err2 in
group.enter()
print("async call")
if err2 == nil {
// do stuff
group.leave()
}
else {
print("\(err2)")
group.leave()
}
}
}
if let ref = notifRecord?.object(forKey: LIBRARY_ITEM) as! CKReference? {
self.db.fetch(withRecordID: ref.recordID) { libRecord, err3 in
group.enter()
print("async call")
if err3 == nil {
// do stuff
group.leave()
}
else {
print("\(err3)")
group.leave()
}
}
}
group.leave()
}
else {
print("\(notifErr)")
group.leave()
}
}
}
group.notify(queue: .main, execute: { // executed after all async calls in for loop finish
print("done with all async calls")
// do stuff
})
从我包含的打印语句中,我知道我的异步调用是不正确的:有时 "done with all async calls" 在 "async call." 的所有实例之前打印任何关于如何让这个调度组正常工作的帮助将是非常感激。谢谢!
问题是第 2 和第 3 个内部异步调用。您在完成块内而不是在异步调用之前调用 group.enter()
。
也不需要那么多次调用leave
。
你需要移动两个如下:
let group = DispatchGroup()
for ref in self.notifsRefList {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { notifRecord, notifErr in
print("async call")
if notifErr == nil {
// do stuff
if let ref = notifRecord?.object(forKey: POST) as! CKReference? {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { postRecord, err in
print("async call")
if err == nil {
// do stuff
}
else {
print("\(err)")
}
group.leave()
}
}
if let ref = notifRecord?.object(forKey: USER_NOTIF) as! CKReference? {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { userRecord, err2 in
print("async call")
if err2 == nil {
// do stuff
}
else {
print("\(err2)")
}
group.leave()
}
}
if let ref = notifRecord?.object(forKey: LIBRARY_ITEM) as! CKReference? {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { libRecord, err3 in
print("async call")
if err3 == nil {
// do stuff
}
else {
print("\(err3)")
}
group.leave()
}
}
}
else {
print("\(notifErr)")
}
group.leave()
}
}
group.notify(queue: .main, execute: { // executed after all async calls in for loop finish
print("done with all async calls")
// do stuff
})
我了解如何在简单的 for 循环中使用调度组。但是,我有一个更复杂的 for 循环,其中包含更多异步调用 。我希望在执行组完成代码之前完成所有异步调用。我试图应用此答案中的原则无济于事-
let group = DispatchGroup()
for ref in self.notifsRefList {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { notifRecord, notifErr in
print("async call")
if notifErr == nil {
// do stuff
if let ref = notifRecord?.object(forKey: POST) as! CKReference? {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { postRecord, err in
print("async call")
if err == nil {
// do stuff
group.leave()
}
else {
print("\(err)")
group.leave()
}
}
}
if let ref = notifRecord?.object(forKey: USER_NOTIF) as! CKReference? {
self.db.fetch(withRecordID: ref.recordID) { userRecord, err2 in
group.enter()
print("async call")
if err2 == nil {
// do stuff
group.leave()
}
else {
print("\(err2)")
group.leave()
}
}
}
if let ref = notifRecord?.object(forKey: LIBRARY_ITEM) as! CKReference? {
self.db.fetch(withRecordID: ref.recordID) { libRecord, err3 in
group.enter()
print("async call")
if err3 == nil {
// do stuff
group.leave()
}
else {
print("\(err3)")
group.leave()
}
}
}
group.leave()
}
else {
print("\(notifErr)")
group.leave()
}
}
}
group.notify(queue: .main, execute: { // executed after all async calls in for loop finish
print("done with all async calls")
// do stuff
})
从我包含的打印语句中,我知道我的异步调用是不正确的:有时 "done with all async calls" 在 "async call." 的所有实例之前打印任何关于如何让这个调度组正常工作的帮助将是非常感激。谢谢!
问题是第 2 和第 3 个内部异步调用。您在完成块内而不是在异步调用之前调用 group.enter()
。
也不需要那么多次调用leave
。
你需要移动两个如下:
let group = DispatchGroup()
for ref in self.notifsRefList {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { notifRecord, notifErr in
print("async call")
if notifErr == nil {
// do stuff
if let ref = notifRecord?.object(forKey: POST) as! CKReference? {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { postRecord, err in
print("async call")
if err == nil {
// do stuff
}
else {
print("\(err)")
}
group.leave()
}
}
if let ref = notifRecord?.object(forKey: USER_NOTIF) as! CKReference? {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { userRecord, err2 in
print("async call")
if err2 == nil {
// do stuff
}
else {
print("\(err2)")
}
group.leave()
}
}
if let ref = notifRecord?.object(forKey: LIBRARY_ITEM) as! CKReference? {
group.enter()
self.db.fetch(withRecordID: ref.recordID) { libRecord, err3 in
print("async call")
if err3 == nil {
// do stuff
}
else {
print("\(err3)")
}
group.leave()
}
}
}
else {
print("\(notifErr)")
}
group.leave()
}
}
group.notify(queue: .main, execute: { // executed after all async calls in for loop finish
print("done with all async calls")
// do stuff
})