Swift-阻止循环直到下载操作完成为止

问题描述:

我目前正在尝试根据用户的游戏请求下载多个文件。我的目标是一次只下载一个文件,并停止执行代码,直到该文件下载完成。

I am currently trying to download multiple files upon user request for a game. My goal is to have it download only one file at a time and stop executing code until that file has finished downloading.

我的代码是一组JSON对象,每个对象包含将它们下载到的路径(path)和文件的URL。我正在遍历数组,并使用AlamoFire通过 .downloadProgress 闭包下载它们。

My code is an array of JSON objects, in each contains a path for where to download them to(path) and the URL of the file. I am looping through the array and using AlamoFire to download them with a .downloadProgress closure.

Alamofire.download(
json["url"].stringValue,
method: .get,
to: destination).downloadProgress(closure: { (Alamoprogress) in
info.stringValue = "Downloading: " + filename
progress.doubleValue = Alamoprogress.fractionCompleted * 100
}).response(completionHandler: { (DefaultDownloadResponse) in
})

为了确保每次仅下载一个文件,我设置了DispatchQueue并将其移动同步操作内部的Alamofire请求:

To try to make sure it only downloaded a single file at a time, I set up a DispatchQueue and moved the Alamofire request inside of synchronous operation:

for jsonObject in jsonArray{
    queue.async {
    print("Started downloading " + filename)
    info.stringValue = "Downloading: " + filename
    info.placeholderString = "Downloading: " + filename
    info.isEnabled = true
    info.isHidden = false
    progress.isHidden = false
    let destination: DownloadRequest.DownloadFileDestination = { _, _ in
        let documentsURL = filepath
        return (documentsURL, [.removePreviousFile])
    }
    Alamofire.download(
        json["url"].stringValue,
        method: .get,
        to: destination).downloadProgress(closure: { (Alamoprogress) in
                info.stringValue = "Downloading: " + filename
            progress.doubleValue = Alamoprogress.fractionCompleted * 100
        }).response(completionHandler: { (DefaultDownloadResponse) in
                            })
           }
}

但是,调试日志将在下载文件时继续循环并下载 a 同步。这会导致 info 框和 progress 栏在下载时发疯,因为它们一次都下载了。我相信我已经建立了一个同步循环,但是它可能仍然是异步的,因为它一直在循环。

However, the debug log will continue to loop while downloading files and will download them asynchronously. This causes the info box and progress bar to go nuts while downloading, as it's downloading them all at once. I believe I have set up a synchronous loop however it may still be asynchronous in that is it looping through.

如何防止此处的异步下载?

How can I prevent asynchronous downloads here?

使用信号量,以便一次只能下载一个信号:

Use a semaphore so only one is downloading at a time:

let semaphore = DispatchSemaphore(value: 1)

for jsonObject in jsonArray {
    queue.async {
        semaphore.wait()

        print("Started downloading " + filename)
        info.stringValue = "Downloading: " + filename
        info.placeholderString = "Downloading: " + filename
        info.isEnabled = true
        info.isHidden = false
        progress.isHidden = false
        let destination: DownloadRequest.DownloadFileDestination = { _, _ in
            let documentsURL = filepath
            return (documentsURL, [.removePreviousFile])
        }
        Alamofire.download( json["url"].stringValue, method: .get, to: destination)
            .downloadProgress{ Alamoprogress in
                info.stringValue = "Downloading: " + filename
                progress.doubleValue = Alamoprogress.fractionCompleted * 100
            }
            .response { response in
                semaphore.signal()
            }
    }
}