当使用dispatch_group_async
本身是异步的方法进行调用时,该组将在所有异步任务启动后立即完成,但不会等待它们完成。相反,您可以dispatch_group_enter
在进行异步调用之前手动调用,然后dispatch_group_leave
在异步调用完成时进行调用。然后dispatch_group_wait
现在将按预期方式运行。
但是,要实现此目的,请首先进行更改downloadImage
以包括完成处理程序参数:
private func downloadImage(serverFile: AdFileInfo, completionHandler: (NSError?)->()) {
let destinationPath = imageDirectoryURL.URLByAppendingPathComponent(serverFile.fileName)
Alamofire.download(.GET, serverFile.imageUrl) { temporaryURL, response in return destinationPath }
.response { _, _, _, error in
if let error = error {
print("Error downloading \(serverFile.fileName): \(error)")
} else {
print("Done downloading \(serverFile.fileName)")
}
completionHandler(error)
}
}
我已经完成了一个传回错误代码的完成处理程序。您可以根据自己的喜好对其进行调整,但希望它可以说明这一想法。
但是,已经提供了完成处理程序,现在,当您进行下载时,您可以创建一个组,在启动每次下载之前“输入”该组,在异步调用完成处理程序时“离开”该组。
但是,dispatch_group_wait
如果您不小心,则可能导致死锁;如果从主线程完成操作,则可能会阻塞UI,等等。更好的是,您可以dispatch_group_notify
用来实现所需的行为。
func downloadImages(_ imageFilesOnServer: [AdFileInfo], completionHandler: @escaping (Int) -> ()) {
let group = DispatchGroup()
var downloaded = 0
group.notify(queue: .main) {
completionHandler(downloaded)
}
for serverFile in imageFilesOnServer {
group.enter()
print("Start downloading \(serverFile.fileName)")
downloadImage(serverFile) { error in
defer { group.leave() }
if error == nil {
downloaded += 1
}
}
}
}
您可以这样称呼它:
downloadImages(arrayOfAdFileInfo) { downloaded in
// initiate whatever you want when the downloads are done
print("All Done! \(downloaded) downloaded successfully.")
}
// but don't do anything contingent upon the downloading of the images here