我有这段代码。它从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(....)
,那么我如何确保调用它的视图正确地通知下载完成呢?
我尝试使用闭包,但我无法让它按我想要的方式返回。我在singleton上有一个属性,我想设置这个值,以便可以全局调用它。我也在考虑使用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
}
}