如何检测到所有30个Alamofire请求都已被回应?

我正在制作一个应用程序,通过将数据显示在图表中,显示过去30天内两种货币之间的汇率。 我正在使用Alamofire和SwiftyJSON来parsing响应。 我使用的API是http://fixer.io 。

在我的视图控制器,我有这个方法称为getRate ,将填充一个字典( [Date: Double] )被称为ratesgetRate将在viewDidLoad中调用,定义如下:

 func getRate() { let baseCurrency = UserDefaults.standard.string(forKey: "baseCurrency") let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" for date in last30Days { let dateString = formatter.string(from: date) let url = "https://api.fixer.io/\(dateString)?base=\(baseCurrency!)&symbols=\(self.currency!)" Alamofire.request(url).responseString { [weak self] response in if let _ = response.error { return } let json = JSON(parseJSON: response.value!) if let _ = json["error"].string { return } if self != nil { if let rate = json["rates"][self!.currency.currencyCode].double { self!.rates[date] = rate } } } } } 

last30Days是一个常量,types为[Date] ,在过去的30天中每天都存储一个Dateself.currency是由另一个视图控制器传递给此视图控制器的枚举types值。 self.currency.currencyCode是一个计算属性,返回由枚举表示的货币的货币代码,例如"GBP" 。 基本上, getRate正在发出30个请求,并将这些响应值添加到rates字典中。

我想要做的就是在30个请求都没有错误的情况下做出响应,根据汇率绘制图表。 目前,我检查字典是否有30个条目。 如果是这样,刷新图表:

 var rates: [Date: Double] = [:] { didSet { if rates.count == 30 { refreshCharts() } } } 

这工作得很好,直到我想添加一个“刷新”button。 当用户刷新时,我想再次做出相同的30个请求。 如果他们都没有错误地成功,用新的价值来填充rates 。 如果发生一个或多个错误,我想保持不变的价值,即保持旧的数据。

要做到这一点,我必须知道什么时候所有的30个请求都被回复,是否有错误。 我不能再使用if rates.count == 30技巧,因为当用户刷新时, rates已经填充了旧值。 我不能在开始时将rates设置为空,因为这将丢失旧数据,当有任何错误时需要显示这些旧数据。 我不能保证在getRate开始时不会有任何错误。

基本上, 我怎么知道什么时候所有的30个请求都被回复,是否发生错误

您可以使用DispatchGroup:

 let group = DispatchGroup() var errors: [Error] = [] for date in last30Days { group.enter() // ... Alamofire.request(url).responseString { defer { group.leave() } guard let error = response.error else { errors.append(error) return } // ... } } group.notify(queue: .main) { // All requests are finished now } 

请注意,errors数组不会是线程安全的(与您的字典相同)。

编辑:为了线程安全,你可以在队列上调度你的更新,以确保variables不会一次从不同的线程被修改。

 let queue = DispatchQueue(label: "queue") var errors: [Error] = [] for date in last30Days { // ... queue.async { errors.append(error) } // ... } 

你可以为你的字典做同样的事情