当所有异步请求都完成时收到通知。只有在完成所有同步请求后才发出信令通知
我在下面的循环中多次呼叫registerTrack
。我只想触发syncGroup.notify
时全部请求已完成。从看这个代码,在registerTrack
每次成功完成之后,它会去notify
。只有在所有registerTrack
操作完成后,我如何才能使其显示notify
?
我的代码如下:
var fail = false
let syncGroup = DispatchGroup() //used so we can determine if all the register requests have finished
for track in unsyncedTracks {
syncGroup.enter()
if fail {
syncGroup.leave()
break //might save an aync request from getting executed on failure
}
registerTrack(track: track, withCompletion: { (success: Bool) ->() in
if success {
self.debug.log(tag: "RecordViewController", content: "Registered track: \(track.name)")
syncGroup.leave()
}
else {
fail = true
syncGroup.leave()
}
})
}
//all requests complete
syncGroup.notify(queue: .main) {
if fail {
complete(false)
}
else {
self.debug.log(tag: "RecordViewController", content: "Finished registering all unsynced tracks")
complete(true)
}
}
编辑:
基于使用GCD并发队列的建议,我改变了我的代码:
var failed = false
//work item to loop through and call registerTrack on each track
let registerTracksWorkItem = DispatchWorkItem {
for track in unsyncedTracks {
if failed { //exit early on failure, potentially save a network request
break
}
self.registerTrack(track: track, withCompletion: { (success: Bool) ->() in
if success {
self.debug.log(tag: "RecordViewController", content: "Registered track: \(track.name)")
}
else {
failed = true
}
})
}
}
//handler for when all registerTrack calls are complete
registerTracksWorkItem.notify(queue: DispatchQueue.main) {
if failed {
self.debug.log(tag: "RecordViewController", content: "At least one registerTrack call failed")
complete(false)
}
else {
self.debug.log(tag: "RecordViewController", content: "Finished registering all unsynced tracks")
complete(true)
}
}
//execute the work item
let queue = DispatchQueue.global()
queue.async(execute: registerTracksWorkItem)
此代码不等待registerTrack
完成,而是执行它们并调用notify
事件。 :(
编辑3:
所以这个作品它使用一个计数器进行检查,看其是否在最后unsyncedTracks
对象
var fail = false
let syncGroup = DispatchGroup() //used so we can determine if all the register requests have finished
//used to make sure notify is only triggered when all registerTracks are complete
let unsyncedTracksCount = unsyncedTracks.count
var completeCounter = 0
syncGroup.enter()
for track in unsyncedTracks {
registerTrack(track: track, withCompletion: { (success: Bool) ->() in
if success {
self.debug.log(tag: "RecordViewController", content: "Registered track: \(track.name)")
}
else {
fail = true
}
completeCounter = completeCounter + 1
if completeCounter == unsyncedTracksCount {
syncGroup.leave()
}
})
}
//all requests complete
syncGroup.notify(queue: .main) {
if fail {
complete(false)
}
else {
self.debug.log(tag: "RecordViewController", content: "Finished registering all unsynced tracks")
complete(true)
}
}
我能做到这一点(它也出现工作。 )?我加了,如果失败,leave()
如果。
var fail = false
let syncGroup = DispatchGroup() //used so we can determine if all the register requests have finished
//used to make sure notify is only triggered when all registerTracks are complete
let unsyncedTracksCount = unsyncedTracks.count
var completeCounter = 0
syncGroup.enter()
for track in unsyncedTracks {
if fail { //might save an aync request from getting executed on failure
syncGroup.leave()
break
}
registerTrack(track: track, withCompletion: { (success: Bool) ->() in
if success {
self.debug.log(tag: "RecordViewController", content: "Registered track: \(track.name)")
}
else {
fail = true
}
completeCounter = completeCounter + 1
if completeCounter == unsyncedTracksCount {
syncGroup.leave()
}
})
}
//all requests complete
syncGroup.notify(queue: .main) {
if fail {
complete(false)
}
else {
self.debug.log(tag: "RecordViewController", content: "Finished registering all unsynced tracks")
complete(true)
}
}
将多个异步调用放入循环中并不是很好的设计。 GCD的并发队列可能非常适合您的问题。这样你可以运行所有的registerTracks任务,并知道它们什么时候全部完成。 https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html – Gruntcakes
@Essenceofchicken你有没有例子?谢谢。 – toast
我在上面添加了一个Apple文档的链接,里面有代码片段。 – Gruntcakes