'How to wait for an API request to finish before storing data from function callback?
In a personal project of mine, I have created an API caller to retrieve a user's saved tracks from the Spotify API. The Spotify endpoint which I am using has a limit (maximum of 50 tracks per request) as well as an offset (starting index of first track in request), which is why I decided to use a FOR loop to get a series of track pages (each 50 tracks) and append them to a global array. The data is loaded from the main thread, and while the data is being requested, I display a child view controller with a spinner view. Once the data request has completed, I remove the spinner view, and transition to another view controller (passing the data as a property).
I have tried many things, but the array of tracks is always empty following the API request. I have a feeling it has to do with the synchronicity of my request, or maybe its possible that I'm not handling it correctly. Ideally, I would like to wait until the request from my API finishes, then append the result to the array. Do you have any suggestions on how I could solve this? Any help is much appreciated!
func createSpinnerView() {
let loadViewController = LoadViewController.instantiateFromAppStoryboard(appStoryboard: .OrganizeScreen)
add(asChildViewController: loadViewController)
DispatchQueue.main.async { [weak self] in
if (self?.dropdownButton.dropdownLabel.text == "My saved music") {
self?.fetchSavedMusic() { tracksArray in
self?.tracksArray = tracksArray
}
}
...
self?.remove(asChildViewController: loadViewController)
self?.navigateToFilterScreen(tracksArray: self!.tracksArray)
}
}
private func fetchSavedMusic(completion: @escaping ([Tracks]) -> ()) {
let limit = 50
var offset = 0
var total = 200
for _ in stride(from: 0, to: total, by: limit) {
getSavedTracks(limit: limit, offset: offset) { tracks in
//total = tracks.total
self.tracksArray.append(tracks)
}
print(offset, limit)
offset = offset + 50
}
completion(tracksArray)
}
private func getSavedTracks(limit: Int, offset: Int, completion: @escaping (Tracks) -> ()) {
APICaller.shared.getUsersSavedTracks(limit: limit, offset: offset) { (result) in
switch result {
case .success(let model):
completion(model)
print("success")
case .failure(let error):
print("Error retrieving saved tracks: \(error.localizedDescription)")
print(error)
}
}
}
private func navigateToFilterScreen(tracksArray: [Tracks]) {
let vc = FilterViewController.instantiateFromAppStoryboard(appStoryboard: .OrganizeScreen)
vc.paginatedTracks = tracksArray
show(vc, sender: self)
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
