I'm building an app that fetches data from the The Movie Database API and presents a List of movies by genre.
In my view model I have a function that calls the api and makes the data available via an observable object.
import Foundation class MovieListViewModel: ObservableObject { @Published var movies = [Movie]() private var fetchedMovies = [MovieList]() var page = 1 func fetchMovies(genre: Int) { WebService().getMoviesByGenre(genre: genre, page: page) { movie in if let movie = movie { self.fetchedMovies.append(movie) for movie in movie.movies { self.movies.append(movie) } } } page += 1 print(page) } } Inside the view, I'm using onAppear to call the function and pass the genre id (Int) received from the previous view. This all works as expected.
import SwiftUI struct MovielistView: View { @ObservedObject private var movielistVM = MovieListViewModel() var genre: GenreElement var body: some View { List { ... } }.onAppear { self.movielistVM.fetchMovies(genre: self.genre.id) } .navigationBarTitle(genre.name) } } The problem is because I'm using onAppear, the api is being hit/the view refreshed every time the user navigates back to the view.
Ideally, I'd like to call the api once during the initialising of the view model but because the genre property hasn't been initialised yet, it can't pass the parameter to the view model.
I'v tried this (below) but get the error 'self' used before all stored properties are initialized
import SwiftUI struct MovielistView: View { @ObservedObject private var movielistVM = MovieListViewModel() var genre: GenreElement init() { movielistVM.fetchMovies(genre: genre.id) // Error here } var body: some View { List { ... } .navigationBarTitle(genre.name) } } Any help would be appreciated.
fetchMovieswill be called every timeMovielistView()is called, with or without parameters, and as it will be for sure in some parent view body, it will be called on every update. Just in case.