Swift(iOS),等待所有图像完成下载后再返回

编程入门 行业动态 更新时间:2024-10-06 22:31:16
本文介绍了Swift(iOS),等待所有图像完成下载后再返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在编写一个Swift iOS应用程序(首先,请耐心等待),在这里我使用Swifter HTTP服务器处理各种请求。这样的请求之一就是带有JSON数组的HTTP POST,该JSON数组指定要从网络下载的图像(并执行其他操作,与当前问题无关)。

I am writing a Swift iOS app (my first, so please bear with me) where I use Swifter HTTP server to process various requests. One such request is an HTTP POST with a JSON array specifying images to download from the web (and do some other stuff, not pertinent to the issue at hand).

I使用Alamofire下载图片(效果很好),但是我正在寻找一种好的(最好是简单的)方式来等待所有图片完成下载,然后返回对以上POST请求的响应(因为该响应必须包含指示JSON的信息)

I use Alamofire to download the images (this works fine), but I am looking for good (preferably simple) way to wait for all the images to finish downloading before returning a response to the POST request above (since the response has to contain JSON indicating the result, including any failed downloads).

什么是完成此操作的好方法(最好不阻塞主线程)?

What is a good way to accomplish this (preferably w/o blocking the main thread)?

下面是一些片段来说明:

Here are some snippets to illustrate:

public func webServer(publicDir: String?) -> HttpServer { let server = HttpServer() server.POST["/images/update"] = { r in let images = ...(from JSON array in body) let updateResult = ImageUtil.updateImages(images) let resultJson: String = Mapper().toJSONString(updateResult, prettyPrint: true)! if updateResult.success { return .OK(.Text(resultJson)) } return HttpResponse.RAW(500, "Error", nil, { $0.write([UInt8](updateResult.errorMessage.utf8)) }) } } static func updateImages(images: [ImageInfo]) -> UpdateResult { let updateResult = UpdateResult() for image in images { Alamofire.download(.GET, serverFile.imageUrl) { temporaryURL, response in return destinationPath } .validate() .response{_, _, _, error in if let error = error { Log.error?.message("Error downloading file \(image.imageUrl) to \(image.fileName): \(error)") } else { updateResult.filesDownloaded++ Log.info?.message("Downloaded file \(image.imageUrl) to \(image.fileName)") }} } return updateResult // It obviously returns before any images finish downloading. I need to wait until all images have downloaded before I can return an accurate result. }

使用每bbum的分发程序更新2016年1月23日

这是尝试使用调度程序机制,但对updateImages的调用仍会立即返回(即使使用dispatch_sync时)。

This is an attempt to use the dispatcher mechanism, but the call to updateImages still return right away (even when using dispatch_sync).

如何在将HTTP响应返回给调用方之前等待所有下载完成?

public func webServer(publicDir: String?) -> HttpServer { let server = HttpServer() server.POST["/images/update"] = { r in let imageDownloader = ImageDownloader() imageDownloader.updateimageFiles(adFilesOnServer) let resultJson: String = Mapper().toJSONString(imageDownloader.updateResult, prettyPrint: true)! if imageDownloader.updateResult.success { return .OK(.Text(resultJson)) } return HttpResponse.RAW(500, "Error", nil, { $0.write([UInt8](imageDownloader.updateResult.errorMessage.utf8)) }) } } class ImageDownloader { var updateResult = AdUpdateResult() private var imageFilesOnServer = [ImageFile]() private let fileManager = NSFileManager.defaultManager() private let imageDirectoryURL = NSURL(fileURLWithPath: Settings.imageDirectory, isDirectory: true) private let semaphore = dispatch_semaphore_create(4) private let downloadQueue = dispatch_queue_create("com.acme.downloader", DISPATCH_QUEUE_SERIAL) func updateimageFiles(imageFilesOnServer: [ImageFile]) { self.imageFilesOnServer = imageFilesOnServer dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) for serverFile in imageFilesOnServer { downloadImageFileFromServer(serverFile) } dispatch_sync(downloadQueue) { dispatch_sync(dispatch_get_main_queue()) { print("done") // It gets here before images have downloaded. } } } private func downloadImageFileFromServer(serverFile: ImageFile) { let destinationPath = imageDirectoryURL.URLByAppendingPathComponent(serverFile.fileName) Alamofire.download(.GET, serverFile.imageUrl) { temporaryURL, response in return destinationPath } .validate() .response { _, _, _, error in if let error = error { Log.error?.message("Error downloading file \(serverFile.imageUrl) to \(serverFile.fileName): \(error)") } else { self.updateResult.filesDownloaded++ Log.info?.message("Downloaded file \(serverFile.imageUrl) to \(serverFile.fileName)") } dispatch_semaphore_signal(self.semaphore) } } }

推荐答案

首先,您真的不想开除ar每张图片的每次请求数没有某种限制。

First, you really don't want to be firing off a request-per-image without some kind of a throttle. Semaphores work well for that sort of thing.

第二,您需要从根本上计算未完成的操作数,然后在完成操作后触发完成处理程序。或者,如果可以随时开始新操作,则可能要对操作进行分组。

Secondly, you need to basically count the number of operations outstanding and then fire a completion handler when they are all done. Or, if new operations can be started at any time, you'll probably want to group operations.

因此,伪代码:

sema = dispatch_semaphore_create(4) // 4 being # of concurrent operations allowed serialQ = dispatch_queue_create(.., SERIAL) dispatch_async(serialQ) { dispatch_semaphore_wait(sema, FOREVER) // will block if there are 4 in flight already for image in images { downloader.downloadAsync(image, ...) { // completion dispatch_semaphore_signal(sema) // signal that we are done with one ... handle downloaded image or error ... ... add downloaded images to downloadedImages ... } } } dispatch_async(serialQ) { // since serialQ is serial, this will be executed after the downloads are done dispatch_async(main_queue()) { yo_main_queue_here_be_yer_images(... downloadedImages ...) } }

更多推荐

Swift(iOS),等待所有图像完成下载后再返回

本文发布于:2023-11-13 02:49:11,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1583220.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:图像   Swift   iOS

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!