如何检测到所有30个Alamofire请求都已被回应?
我正在制作一个应用程序,通过将数据显示在图表中,显示过去30天内两种货币之间的汇率。 我正在使用Alamofire和SwiftyJSON来parsing响应。 我使用的API是http://fixer.io 。
在我的视图控制器,我有这个方法称为getRate
,将填充一个字典( [Date: Double]
)被称为rates
。 getRate
将在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天中每天都存储一个Date
。 self.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) } // ... }
你可以为你的字典做同样的事情