I have a function:
func fetchHistoricalCurrencyData(completion: @escaping (() -> ())) {
let g = DispatchGroup()
DispatchQueue.main.async { [weak self] in
var historicalCurrencyDataTemp = [HistoricalCurrencyDataModel]()
let dayDurationInSeconds: TimeInterval = 60*60*24
for date in stride(from: self!.startingDate, to: self!.endingDate, by: dayDurationInSeconds) {
g.enter()
APIManager.shared.getHistoricalCurrencyData(date: self!.convertDateToStringDate(date: date), fromCurrency: String(self!.fromCurrency.prefix(3)), amount: self!.amount, toCurrency: String(self!.toCurrency.prefix(3))) {
historicalCurrencyDataModel in
historicalCurrencyDataTemp.append(historicalCurrencyDataModel)
DispatchQueue.main.asyncAfter(deadline: .now() 1) {
g.leave()
}
}
}
g.notify(queue:.main) {
self?.historicalCurrencyData = DataManager.shared.getHistoricalCurrencyData(historicalCurrencyDataModels: historicalCurrencyDataTemp)
print(self?.historicalCurrencyData)
completion()
}
}
}
What's more, I have a dateRange which I divide into particular days within this range by using stride()
function. Every day I get from this function I use to make an API Call to get desired data. Every API data I get is being converted to particular HistoricalCurrencyDataModel
and appended to temp array which I create before the loop (historicalCurrencyDataTemp
). When I receive all the data I want I use DataManager
class to transform this data into [String: Double]
dictionary which I finally assign to my @Published var historicalCurrencyData: [String: Double]
variable.
One clue thing is that API I use make it possible to make API calls one after another at least after 1 second so I have to create 1 second delay between each call. I made it possible with DispatchQueue.main.asyncAfter(deadline: .now() 1)
statement. I control the whole flow of asynchronous operations with DispatchGroup()
.
Unfortunately after all of this what I get is empty Optional([:])
within print(self?.historicalCurrencyData)
statement. And for example the correct behaviour would be that if I use dateRange with 5 days I get a dictionary with 5 entries.
CodePudding user response:
I ultimately got rid of all DispatchQueues
and now it works as it should. I believe there was something wrong with the delay and not all values were fetched correctly. What's more, I discovered that there is no need of creating 1 second between API calls I thought otherwise after reading API documentation. I must have been wrong.
As suggested (which I agree with) I attach working code:
func fetchHistoricalCurrencyData(completion: @escaping (() -> ())) {
let g = DispatchGroup()
var historicalCurrencyDataTemp = [HistoricalCurrencyDataModel]()
for date in stride(from: self.startingDate, to: self.endingDate, by: dayDurationInSeconds) {
g.enter()
APIManager.shared.getHistoricalCurrencyData(date: self.convertDateToStringDate(date: date), fromCurrency: String(self.fromCurrency.prefix(3)), amount: self.amount, toCurrency: String(self.toCurrency.prefix(3))) {
historicalCurrencyDataModel in
historicalCurrencyDataTemp.append(historicalCurrencyDataModel)
g.leave()
}
}
g.notify(queue:.main) {
self.historicalCurrencyData = DataManager.shared.getHistoricalCurrencyData(historicalCurrencyDataModels: historicalCurrencyDataTemp)
print(self.historicalCurrencyData)
completion()
}
}