Swift,dispatch_group_wait不等待

我正在尝试使用中央集中调度来等待文件完成下载再继续。这个问题是从以下问题衍生出来的:Swift(iOS),等待所有图像下载完成后再返回。

我只是在尝试找出如何使dispatch_group_wait(或类似的方法)真正等待,而不仅仅是在下载完成之前继续。请注意,如果我使用NSThread.sleepForTimeInterval而不是调用downloadImage,它会等待就好。

我想念什么?

class ImageDownloader {

var updateResult = AdUpdateResult()

private let fileManager = NSFileManager.defaultManager()

private let imageDirectoryURL = NSURL(fileURLWithPath: Settings.adDirectory, isDirectory: true)

private let group = dispatch_group_create()

private let downloadQueue = dispatch_queue_create("com.acme.downloader", DISPATCH_QUEUE_SERIAL)

func downloadImages(imageFilesOnServer: [AdFileInfo]) {

dispatch_group_async(group, downloadQueue) {

for serverFile in imageFilesOnServer {

print("Start downloading \(serverFile.fileName)")

//NSThread.sleepForTimeInterval(3) // Using a sleep instead of calling downloadImage makes the dispatch_group_wait below work

self.downloadImage(serverFile)

}

}

dispatch_group_wait(group, DISPATCH_TIME_FOREVER); // This does not wait for downloads to finish. Why?

print("All Done!") // It gets here too early!

}

private func downloadImage(serverFile: AdFileInfo) {

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 {

self.updateResult.filesDownloaded++

print("Done downloading \(serverFile.fileName)")

}

}

}

}

注意:这些下载是对HTTP

POST请求的响应,并且我使用的是不支持异步操作的HTTP服务器(Swifter),因此在返回响应之前,我确实需要等待完整的下载完成(请参阅引用的原始问题)上方以获取更多详细信息)。

回答:

当使用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

以上是 Swift,dispatch_group_wait不等待 的全部内容, 来源链接: utcz.com/qa/421632.html

回到顶部