Hi everyone! At the moment, I am taking a course at the Harvard computer science CS50. My homework is almost ready, but has some incompleteness. I cannot assign a value from a function to a variable in the class or pass this value to the next function.
import UIKit
class PokemonViewController: UIViewController {
var url: String!
var name: String!
@IBOutlet var pokemonImage: UIImageView!
@IBOutlet var nameLabel: UILabel!
@IBOutlet var numberLabel: UILabel!
@IBOutlet var type1Label: UILabel!
@IBOutlet var type2Label: UILabel!
@IBOutlet var catchButton: UIButton!
@IBOutlet var descriptionLabel: UILabel!
// MARK: - additional properties
var currentDescURL: String!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadPokemon()
showPokemonDescription()
}
//MARK: - pokemon loading
func loadPokemon() {
guard let pokemonURL = URL(string: url) else { return }
URLSession.shared.dataTask(with: pokemonURL) { (data, _, error) in
guard let data = data else { return }
do {
let result = try JSONDecoder().decode(PokemonResult.self, from: data)
DispatchQueue.main.async {
self.navigationItem.title = self.capitalize(text: result.name)
self.nameLabel.text = self.capitalize(text: result.name)
self.numberLabel.text = String(format: "#%03d", result.id)
for typeEntry in result.types {
if typeEntry.slot == 1 {
self.type1Label.text = typeEntry.type.name
}
else if typeEntry.slot == 2 {
self.type2Label.text = typeEntry.type.name
}
}
// Create Image and Update ImageView
guard let imageURL = URL(string: result.sprites.front_default) else { return }
if let data = try? Data(contentsOf: imageURL) {
self.pokemonImage.image = UIImage(data: data)
}
self.currentDescURL = result.species.url
print(self.currentDescURL)
}
} catch let error { print(error) }
}.resume()
}
// MARK: - Get the URL of a specific Pokémon
func showPokemonDescription() {
guard let pokemonDescriptionURL = URL(string: currentDescURL) else { return }
URLSession.shared.dataTask(with: pokemonDescriptionURL) { (data, _, error) in
guard let data = data else { return }
do {
let result = try JSONDecoder().decode(PokemonDescription.self, from: data)
DispatchQueue.main.async {
// Check and get first pokemon description in English
for index in 0..<result.flavor_text_entries.count {
if result.flavor_text_entries[index].language.name == "en" {
self.descriptionLabel.text = result.flavor_text_entries[index].flavor_text
}
}
}
} catch let error { print(error) }
}.resume()
}
}
The first function loadPokemon() inside itself gets value from JSON and prints the value to the console -> print(self.currentDescURL). Moreover, if you display this value in viewWillAppear, then "nil" will be displayed in the console. I understand that the loadPokemon() function processes the values in the stream that occur at the very end. Perhaps because of this, the variable currentDescURL cannot get the value from the loadPokemon() function and the showPokemonDescription() function cannot use this value since currentDescURL is nil.
I ask you to explain to me what my mistake is and to help finish the assignment.
Move the call for method showPokemonDescription
from viewWillAppear
to loadPokemon
after the currentDescURL
property is set.
class PokemonViewController: UIViewController {
//...
var currentDescURL: String!
//...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadPokemon()
getPreferences()
// <- remove the call from here
}
//...
func loadPokemon() {
//...
self.currentDescURL = result.species.url
self.showPokemonDescription() // <- move the call here
}
//...
func showPokemonDescription() {
//...
}
}