Swift 如何等待下载完成后再继续?

Swift 如何等待下载完成后再继续?,swift,asynchronous,grand-central-dispatch,Swift,Asynchronous,Grand Central Dispatch,我有这段代码。它从API获取数据并将其添加到locationDetails数组中,该数组是单例的一部分 private func DownloadLocationDetails(placeID: String) { let request = AF.request(GoogleAPI.shared.getLocationDetailsLink(placeID: placeID)) request.responseJSON { (data) in

我有这段代码。它从API获取数据并将其添加到
locationDetails
数组中,该数组是单例的一部分

private func DownloadLocationDetails(placeID: String) {
        let request = AF.request(GoogleAPI.shared.getLocationDetailsLink(placeID: placeID))
        request.responseJSON { (data) in
            
            guard let detail = try? JSONDecoder().decode(LocationDetailsBase.self, from: data.data!),
                  let result = detail.result else {
                print("Something went wrong fetching nearby locations.")
                return
            }
            DownloadManager.shared.locationDetails.append(result)
        }
    }
这段代码就是有问题的代码块。我正在创建一个只下载新信息并保留任何旧信息的缓存系统。这样做是为了保存对API的调用并提高性能。行
DownloadLocationDetails(placeID:placeID)
对我来说是个问题,因为如果我执行这行代码,它将继续使用不必要的API调用反复循环,同时等待下载完成。我如何有效地管理这一点

func GetLocationDetail(placeID: String) -> LocationDetail {
        for location in locationDetails {
            if location.place_id == placeID { return location }
        }
        DownloadLocationDetails(placeID: placeID)
        return GetLocationDetail(placeID: placeID)
    }
我希望每当用户与接口对象交互时都会调用这个
GetLocationDetail(..)
,那么我如何确保调用它的视图被正确地通知下载已完成


我试图使用一个闭包,但我无法让它返回我想要的方式。我在单例上有一个属性,我想设置这个值,以便可以全局调用它。我也在考虑使用GCD,但我不确定它的结构。

一般来说,这样做的模式是存储您在
DownloadLocationDetails
中创建的请求对象,这样您可以在进行另一次调用之前检查一个对象是否处于活动状态。如果您一次只想支持一个请求,那么只需保留对请求对象的简单引用即可,但您可以创建一个请求对象字典,并将其键入placeID(您可能需要考虑最大请求数,并排队等待其他请求)

然后技巧是在给定的请求对象完成时得到通知。有几种方法可以做到这一点,例如保留一个回调列表,以便在回调完成时调用,但最简单的方法可能是稍微重构代码,以便在请求完成时始终更新UI,例如:

private func DownloadLocationDetails(placeID: String) {
        let request = AF.request(GoogleAPI.shared.getLocationDetailsLink(placeID: placeID))
        request.responseJSON { (data) in
            
            guard let detail = try? JSONDecoder().decode(LocationDetailsBase.self, from: data.data!),
                  let result = detail.result else {
                print("Something went wrong fetching nearby locations.")
                return
            }
            DownloadManager.shared.locationDetails.append(result)
            // Notify the UI to refresh for placeID
        }
    }
不要等,通知我。添加完成处理程序。