Swift code not showing the newly fetched page, the movie database api

35 Views Asked by At

I want to fetch page 2 and up when the button 'load more' is pressed. The console log shows that the url fetches the second page content and up, but the app keeps showing the first page content. The already loaded pages should stay there as wel. So if I press load more, page 1 and 2 (and so on) should remain visible.

Here is the fetching code

class MovieStore: MovieService {

@Published var movies = [Movie]()

static let shared = MovieStore()
private init() {}

private let apiKey = "API_KEY"
let baseAPIURL = "https://api.themoviedb.org/3"
let urlSession = URLSession.shared
let jsonDecoder = Utils.jsonDecoder

func fetchMovies(from endpoint: MovieListEndpoint, page: Int, completion: @escaping (Result<MovieResponse, MovieError>) -> ()) {
    guard let url = URL(string: "\(baseAPIURL)/movie/\(endpoint.rawValue)?api_key=\(apiKey)&page=\(page)") else {
        completion(.failure(.invalidEndpoint))
        return
    }
    self.loadURLAndDecode(url: url, completion: completion)
    print(url)
}

the loading code

class MovieListState: ObservableObject {
@Published var movies: [Movie] = []
@Published var isLoading: Bool = false
@Published var error: MovieError?

private let movieService: MovieService
private var currentPage: Int = 1

init(movieService: MovieService = MovieStore.shared) {
    self.movieService = movieService
}

func loadMovies(from endpoint: MovieListEndpoint, page: Int) {
    self.isLoading = true
    self.movieService.fetchMovies(from: endpoint, page: page) { [weak self] (result) in
        guard let self = self else { return }
        self.isLoading = false
        switch result {
        case .success(let response):
            self.movies = response.results

        case .failure(let error):
            self.error = error
        }
    }
}

func fetchNextPage(from endpoint: MovieListEndpoint) {
    guard !isLoading else { return }
    let nextPage = currentPage + 1
    loadMovies(from: endpoint, page: nextPage)
    currentPage = nextPage
 }
}

The page code

struct MovieFullListView: View {
@ObservedObject private var movieListState: MovieListState

let title: String
let endpoint: MovieListEndpoint

@State private var loggedIn = false

@State var selection = 0

@State private var watchedOn = false
@State private var savedOn = false
@State private var isScrolledToEnd = false

var items: [GridItem] = [GridItem(.flexible(), spacing: 20), GridItem(.flexible(), spacing: 20)]

init(title: String, endpoint: MovieListEndpoint) {
    self.title = title
    self.endpoint = endpoint
    self.movieListState = MovieListState()
}

var body: some View {
    VStack(alignment: .leading, spacing: 16) {
        Text(title)
            .font(.title)
            .fontWeight(.bold)
            .padding(.horizontal)
        
        ScrollView(.vertical, showsIndicators: false) {
            LazyVGrid(columns: items, spacing: 30) {
                ForEach(movieListState.movies) { movie in
                    VStack {
                        NavigationLink(destination: MovieDetailView(movieId: movie.id)) {
                            MoviePosterCard(movie: movie)
                                .aspectRatio(contentMode: .fit)
                        }
                        .buttonStyle(.plain)
                        
                        HStack {
                            Spacer()
                            
                            Button(action: {
                                // Watch button
                                if UserDefaults.standard.getLoggedIn() {
                                    let watchedState = !UserDefaults.standard.getWatchedState(forMovieId: movie.id)
                                    UserDefaults.standard.setWatchedState(value: watchedState, forMovieId: movie.id)
                                }
                            }) {
                                VStack {
                                    if !UserDefaults.standard.getLoggedIn() {
                                        Image("Watch (locked)")
                                            .resizable()
                                            .frame(width: 25, height: 25)
                                    } else if UserDefaults.standard.getLoggedIn(), watchedOn {
                                        Image("Watched")
                                            .resizable()
                                            .frame(width: 25, height: 25)
                                    } else {
                                        Image("Watch")
                                            .resizable()
                                            .frame(width: 25, height: 25)
                                    }
                                }
                                .disabled(!UserDefaults.standard.getLoggedIn())
                            }
                            
                            Spacer()
                            
                            Button(action: {
                                // Save button
                                if UserDefaults.standard.getLoggedIn() {
                                    let savedState = !UserDefaults.standard.getSavedState(forMovieId: movie.id)
                                    UserDefaults.standard.setSavedState(value: savedState, forMovieId: movie.id)
                                }
                            }) {
                                VStack {
                                    if !UserDefaults.standard.getLoggedIn() {
                                        Image("Save (locked)")
                                            .resizable()
                                            .frame(width: 25, height: 25)
                                    } else if savedOn {
                                        Image("Saved")
                                            .resizable()
                                            .frame(width: 25, height: 25)
                                    } else {
                                        Image("Save")
                                            .resizable()
                                            .frame(width: 25, height: 25)
                                    }
                                }
                                .disabled(!UserDefaults.standard.getLoggedIn())
                            }
                            
                            Spacer()
                        }
                        .padding(.bottom, 6)
                    }
                    .background(Color.gray.opacity(0.1))
                    .cornerRadius(10)
                }
            }
            Button(action: {
                movieListState.fetchNextPage(from: endpoint)
            }) {
                Text("Load More")
                    .font(.headline)
                    .foregroundColor(.blue)
                    .padding()
                    .background(Color.gray.opacity(0.1))
                    .cornerRadius(10)
            }
            .padding()
        }
    }
    .onAppear {
        loadInitialMovies()
    }
}

private func loadInitialMovies() {
    movieListState.loadMovies(from: endpoint, page: 1)
 }
}

Any idea what could cause it?

0

There are 0 best solutions below