as a newbie I got a problem. This is my custom model for API that I use which is called Poke API.
import UIKit
struct Pokemon: Codable {
var results: [PokemonEntry]
}
struct PokemonEntry: Codable {
var name: String
var url: String
}
And this is the service that I use to get data from API:
import Foundation
class Webservice {
func getData(completion: @escaping (Pokemon?, Error?) -> () ) {
guard let url = URL(string: "https://pokeapi.co/api/v2/pokemon?limit151") else {return}
URLSession.shared.dataTask(with: url) { data, res, err in
if let err = err {
completion(nil, err)
return
}
do {
let pokemons = try JSONDecoder().decode(Pokemon.self, from: data!)
completion(pokemons, nil)
// pokemons.results.forEach({print($0.name)})
} catch {
completion(nil, error)
print(error.localizedDescription)
}
}.resume()
}
}
So in my viewController, I wanna get the pokemon object that returned from Webservice().getData function so I can use wherever I want but it comes as a nil, I can use it only inside of Webservice function's closure.
import UIKit
class ViewController: UIViewController {
var pokeList: Pokemon?
override func viewDidLoad() {
super.viewDidLoad()
Webservice().getData { pokemonResponse, error in
if let error = error {
print(error.localizedDescription)
}
self.pokeList = pokemonResponse
print("I can use pokeList here: \(self.pokeList?.results)")
}
print("I cant use pokeList out of Webservice closure, its nil: \(print(pokeList?.results))")
}
}
CodePudding user response:
Try this instead:
class ViewController: UIViewController {
var pokeList: Pokemon? {
didSet {
print("I can use pokeList out of the Webservice closure, it is: \(pokeList?.results ?? "<nil>")")
}
}
override func viewDidLoad() {
super.viewDidLoad()
Webservice().getData { pokemonResponse, error in
if let error = error {
print(error.localizedDescription)
}
self.pokeList = pokemonResponse
print("I can use pokeList here: \(self.pokeList?.results)")
}
}
}
The problem was that you were using pokeList before it got filled by the web service. It worked as follows:
- Web service task gets started (waits for a response asynchronously)
- Either response is received or your print outside of the block is called which already wants to use what gets filled in the block. The print is usually faster which results in the bug (also known as a race condition)