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?