- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试使用 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/
我在等待 **同步** 对 Facebook Graph API 的async 调用时遇到问题。 var message: String? = "" var error: ErrorType? let
这个问题是关于 Grand Central Dispatch 的,尤其是 dispatch_group_wait()。 假设一个名为 group 的 dispatch_group 中有 10 个任务等
因此,我将一组图像发布到我的服务器。我想使用 GCD 异步发布数组,但我也想使发生这种情况的方法同步,以便我可以传回单个响应对象。然而,方法 dispatch_group_wait 似乎立即返回(而不
我正在尝试使用 grand central dispatch 来等待文件完成下载,然后再继续。这个问题是这个问题的衍生问题:Swift (iOS), waiting for all images to
我正在研究 dispatch_async() 的工作原理。 我在 main() 中试过这个片段: typedef void(^VoidBlock)(); VoidBlock aBlock = ^{
我的代码看起来像这样: [SVProgressHUD show]; [imageGenerator generateCGImagesAsynchronouslyForTimes:times
我有两个获取值的操作。我只关心两个值的总和。如果花费的时间太长,我根本不关心值(value)。 所以我认为使用组对 GCD 来说是一件容易的事。不幸的是,下面的代码只能在 iOS 9 上正常工作。每次
我试图弄清楚 NSRunLoop 有什么特殊属性会导致以下行为。 首先,我要做的是等待 CLGeocoder 完成执行后再继续。如果我使用完成 block ,代码将如下所示: if (/* loc h
我是一名优秀的程序员,十分优秀!