gpt4 book ai didi

ios - swift ,dispatch_group_wait 不等待

转载 作者:搜寻专家 更新时间:2023-10-30 21:49:12 33 4
gpt4 key购买 nike

我正在尝试使用 grand central dispatch 来等待文件完成下载,然后再继续。这个问题是这个问题的衍生问题:Swift (iOS), waiting for all images to finish downloading before returning .

我只是想找出如何让 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 2 和 Alamofire 3 的答案,请参阅 previous revision of this answer .

关于ios - swift ,dispatch_group_wait 不等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34983370/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com