0

I wanted to learn more about tableview and fetching data from rest api so I choose themoviedb to exercise with. For every movie, under its title, I want to represent movie genres.

Movie details - are on this link

As you can see, movie genres are represented with Int values for every genre.

Genre names for every Int(id) are on this link

I wanted to represent genres like for example "Horror, Thriller, Drama".

I made this function to get genres values in [Genre] array.

var genreList: [Genres] = []

func getGenres() {
    MovieServiceAPI.shared.fetchGenres(from: .genre) { (result: Result<GenresResponse, MovieServiceAPI.APIServiceError>) in
        switch result {
        case .success(let genreResponse):
            self.genreList = genreResponse.genres
        case .failure(let error):
            print(error.localizedDescription)
        }
    }
}

After that, I made function which as parameter gets Int array (which represents movie genre ids), and function add genre name for proper id into empty string.

func checkGroups(groups: [Int]) -> String{
    
    var genres: String = ""
    getGenres()
    
    for genre in groups {
        
        genreList.forEach({
            
            if genre == $0.id {
                genres.append($0.name)
                genres.append(", ")
            }
            
        })
    }
    return genres
}

Function is called in configureCell function where values are set.

 func configureCell(movieName: String, groupNames: [Int], imageUrl: String, date: String) {
    movieTitleLabel.text = movieName
    groupsLabel.text = checkGroups(groups: groupNames)
    movieImageView.downloadImage(from: imageUrl)
    dateLabel.text = String(date.prefix(4))
}

configureCell function is called in tableView cellForRowAt function

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cropCell = tableView.dequeueReusableCell(withIdentifier: "movieTableViewCell", for: indexPath) as? MovieTableViewCell else {
        print("failed to dequeue the wanted cell")
        return UITableViewCell()
    }
    let movie = movieList[indexPath.row]
    
    cropCell.configureCell(movieName: movie.title, groupNames: movie.genreIds, imageUrl: movie.backdropPath, date: movie.releaseDate)
    return cropCell
}

Problem is that im getting empty value for groupsLabel.text. Other label values are working fine, only groupsLabel is empty. Where am I getting wrong?

  • 1
    It’s clear you didn’t learn anything from your previous question, the for loop in checkGroups is executed before any genres have been downloaded. Go back and check your previous question to learn about asynchronous programming. And why do you want to download genres each time checkGroups is called, doing it one time should be enough. – Joakim Danielson Jul 03 '21 at 10:19
  • You can't write your function `getGenres()`, call it, expect it to make an ASYNC call, and for the results to be available when it returns. You need to rewrite the function `getGenres()` as `getGenres(completion:)` (with a completion handler) and put the code that installs the results into your table view into the completion handler. – Duncan C Jul 03 '21 at 11:12
  • Analogy: "Go to the store and get me a dozen eggs. Once you get back, use these instructions to make a custard. (The instructions are the completion handler.) You can't make the custard (process the genres) until the async event (network call/buying eggs) is complete. The genres from network call isn't complete/eggs are not available the instant you finish asking for them. You don't freeze, waiting for eggs/waiting for the network call to complete. – Duncan C Jul 03 '21 at 11:15

0 Answers0