Swift 完成和循环问题

Swift Completion & Loop Issue

正在尝试从三个 url 之一下载 PKG 文件。该逻辑基本上从每个下载 url 中找到一个下载的延迟,并将最终下载 url 设置为延迟最低的主机。

import Cocoa
import Alamofire

// Create my object via Struct
struct Package {
    var latency: Double?
    var name: String?
    var statuscode: Int?
    var download: Bool?
    var downloadUrl: String? 
}
// Download the package from the provided download url and return the object
func getPKG(pkgName: String, dpUrl: String, completion: @escaping (Package) -> (Package)) {
    let url = URL(string: "\(dpUrl)\(pkgName)")
    let parameters: Parameters = ["foo":"bar"]
    Alamofire.download(url, method: .get, parameters: parameters, encoding: JSONEncoding.default, to: destination)
        .downloadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
            debugPrint("Download Progress...: \(progress.fractionCompleted)")
        }
        .validate(statusCode: 200..<399)
        .response { response in
            debugPrint(response.response!)
            debugPrint(response.response!.statusCode)
            debugPrint(response.timeline.latency)
            let dlObject = Package(latency: response.timeline.latency, name: pkgName, statuscode: response.response?.statusCode, download: true, downloadUrl: dpUrl)
            completion(dlObject)
    }

}

var share_response = [String: Double]()
var package_sources: NSArray! = ["https://www.jss1.com/Share", "https://www.jss2.com/Share", "https://www.jss3.com/Share"]
let package_names: String = ["Dummy1.pkg", "Dummy2.pkg", "Dummy3.pkg"]
// Loop through the package sources and find the one with 
// the lowest latency.
for share_url in package_sources {
    getPKG(pkgName: "Dummy.pkg", dpUrl: share_url, completion: {
        dlObject in
        if dlObject.latency != nil {
            share_response[share_url] = dlObject.latency
        } else {
            debugPrint("nothing yet")
        }
        return dlObject
    })
}

let final_download_url = share_response.min { a, b in a.value < b.value }

//  Here is where it breaks and responds with nil

for package in package_names {
    let download_url = URL(string: final_download_url + package)
    Download commands here...
}

这是通过遍历每个下载 url 并使用键作为 url 和值作为延迟填充字典来完成的。当脚本继续从 "fastest" 下载 url 下载时,它失败并返回 nil。

我假设这是因为脚本在继续,而完成处理程序仍然是 运行,字典中还没有任何内容,但我该如何解决这个问题?

基于@vadian 在

的回答
...

let group = DispatchGroup()
var share_response = [String: Double]()
var package_sources: NSArray! = ["https://www.jss1.com/Share", "https://www.jss2.com/Share", "https://www.jss3.com/Share"]
let package_names: String = ["Dummy1.pkg", "Dummy2.pkg", "Dummy3.pkg"]
// Loop through the package sources and find the one with 
// the lowest latency.
for share_url in package_sources {
    group.enter()
    getPKG(pkgName: "Dummy.pkg", dpUrl: share_url, completion: {
        group.leave()
        dlObject in
        if dlObject.latency != nil {
            share_response[share_url] = dlObject.latency
        } else {
            debugPrint("nothing yet")
        }
        return dlObject
    })
}

group.notify(queue: DispatchQueue.main) {    
    let final_download_url = share_response.min { a, b in a.value < b.value }

    //  Here is where it breaks and responds with nil

    for package in package_names {
        let download_url = URL(string: final_download_url + package)
        Download commands here...
    }
}