Диспетчерская группа: for-loop * и * асинхронные вызовы внутри цикла for
Я понимаю, как использовать группу отправки в простой цикл 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
})
Из операторов печати, которые я включил, я знаю, что мои асинхронные вызовы неверны: иногда "сделано со всеми асинхронными вызовами" печатает перед всеми экземплярами "асинхронного вызова". Буду очень признателен за любую помощь в правильной работе этой диспетчерской группы. Спасибо!
1 ответ
Проблема в 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
})