I am facing an issue when trying to retrieve and decode JSON data from an API. I am able to get the data from the API and decode it successfully, but I can't access it from outside the function scope. I am using the following function to get and decode data. The API returns an array of JSON objects.
func getJSON(completed: @escaping () -> ()) {
var jsonData = [API_data] () // A struct for retrieved data
let url = "URL Here" // I have the original URL here, which I can't share
let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { [self]data,response,error in
guard let data = data, error == nil else{
print("error")
return
}
do{
jsonData = try JSONDecoder().decode([API_data].self,from:data)
} catch{
print(error)
}
print(jsonData[0].id) // This prints my data
})
print(jsonData[0].id) // This won't print my data
task.resume()
}
struct API_data: Codable {
let id : String
}
As a result of this, I cannot use this data anywhere in the application. Any help will be appreciated. I have also tried making jsonData a global variable, updating it in the function and returning it and then using it, still doesn't work.
Thanks for your help.
CodePudding user response:
As you already have a completion handler use it and pass the received data
func getJSON(completed: @escaping ([API_data]) -> Void) {
let url = "URL Here" // I have the original URL here, which I can't shar
let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _ , error in
if let error = error { print(error); return }
do {
completed(try JSONDecoder().decode([API_data].self,from:data!))
} catch{
print(error)
}
}
task.resume()
}
and use it
getJSON { apiData in
print(apiData[0].id) // This prints my data
}
Or more comfortable with the Result
type
func getJSON(completed: @escaping (Result<[API_data],Error>) -> Void) {
let url = "URL Here" // I have the original URL here, which I can't shar
let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _ , error in
if let error = error { completed(.failure(error)); return }
Result { try JSONDecoder().decode([API_data].self,from: data!) }
}
task.resume()
}
getJSON { result in
switch result {
case .success(let apiData): print(apiData[0].id) // This prints my data
case .failure(let error): print(error)
}
}
CodePudding user response:
It is asynchronous, you might want to access it a bit later when it’s ready, e.g. by using the completion handler.
CodePudding user response:
Try creating a completion handler from your API function and send the data with the completion. And try using it there.