0

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.

1
  • Be aware that your fetchMovies will be called every time MovielistView() 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. Commented Jun 28, 2020 at 19:16

1 Answer 1

1

Add a genre parameter for the init and initialize the genre property of MovielistView before using it:

struct MovielistView: View { var genre: GenreElement //... init(genre: GenreElement) { self.genre = genre movielistVM.fetchMovies(genre: genre.id) } //... } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.