I'm loading data from an API, and expecting my app to show the data once it's loaded.
In my View Model file, here's the code: It calls a WeatherService to get the data, and populates the weather property. Weather is a struct in this case.
class WeatherViewModel: ObservableObject {
let webService = WeatherService.shared
@Published var weather:Weather?
init() {
}
func getWeather() {
webService.getWeather { weather in
if let weather = weather {
self.weather = weather
}
}
}
}
In my SwiftUI view, here's the code:
- I instantiate an instance of the View Model as an ObservedObject
- In the inAppear, I call the method in the view model to get the data
- The first time the screen launches (using a tab bar), I see "Loading weather..." and it never goes away
- If I navigate to a different tab and back, I see the weather. I can't tell if this is data from the old API call, or from the new one.
struct WeatherView: View {
@ObservedObject var weatherViewModel = WeatherViewModel()
@State var areDetailsHidden = true
var body: some View {
VStack(alignment: .leading, spacing: 0) {
if(weatherViewModel.weather == nil) {
Text("Loading weather...")
} else {
Text("Display the weather here")
}
}
.onAppear{
self.weatherViewModel.getWeather()
}
}
}
The weird thing is, if I remove the getWeather() from the onAppear and add it to the init() of the View Model, it works (although for some reason getWeather() gets called twice...). However, I want the weather info to be refreshed every time the screen is loaded.
weatherViewModelis owned by theWeatherView. When it changes that causes the view to be rendered again which creates a newweatherViewModeland you are in an endless loop; You need to move the model out of the view. - Upholder Of Truth