我正在尝试使用中央集中调度来等待文件完成下载再继续。这个问题是从以下问题衍生出来的: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的iTunesU中的“开发适用于iPhone和iPad的ios7应用程序”中复制斯坦福Matchismo游戏。 在第3讲幻灯片的第77页上,它显示了使用,这不是Swift上的选项。Swift文档示例显示了一个具有数组的示例,但是我不知道如何使Interface Builder将多个插座连接到同一个/ Array。 有人知道如何做到这一点吗? 我知道我可以创建1
问题内容: 是否有斯威夫特的本地等效于? 假设我有两个包含键和值的数组,并想将它们放入字典中。在Objective-C中,我会这样做: 当然,我可以遍历两个数组的计数器,使用a 并逐步添加内容。但这似乎不是一个好的解决方案。同时使用和可能是更好的迭代方式。但是,这种方法意味着拥有可变的字典,而不是不可变的字典。 问题答案: 从 Swift 4开始, 您可以直接从键/值对序列创建字典: 这假定所有键
在Swift中,字符串中的的等价物是什么 我尝试了以下操作,但收到一条错误消息
问题内容: 我发现Swift数值特别笨拙,因为在现实生活中经常发生这种情况,我必须就CGRect和CGPoint与Cocoa Touch交流(例如,因为我们在谈论某事或)。 CGFloat vs.双 考虑下面的来自UIViewController子类的看上去无辜的代码: 该代码无法编译,最后一行出现通常的神秘错误: 找不到接受提供的参数的’*’的重载 我现在已经确定,这个错误表明类型之间的某种阻抗
问题内容: 我已经用谷歌搜索,但无法找出什么是等效的。 这是我唯一能找到的(Swift的替代方法responsesToSelector:),但在我的情况下并没有太大意义,因为它检查了委托的存在,我没有委托,我只想检查是否存在新的API在设备上运行时是否返回,如果不是,则返回原先的api版本。 问题答案: 如前所述,在 大多数情况下,您可以使用可选的unwrapper运算符来实现所需的功能。这样,当
问题内容: 我不确定如何处理这种情况,因为我是iOS开发和Swift的新手。我正在像这样执行数据获取: 我的loadShows()函数解析从加载到UIWebView的网站中获取的大量数据。问题是我在loadShows函数中有一个等待10秒钟左右的计时器。这允许页面中的javascript在开始解析数据之前完全加载。我的问题是完成处理程序在我的loadShows()之前完成。 我想做的是为“ isC