I have a view inside my project that have a @StateObject viewModel that is not initialized when the view is init.
So when the viewModel property is triggered inside the body, I'll get the following warning: Accessing StateObject's object without being installed on a View. This will create a new instance each time.
I understand that StateObject wrappers have a @autoclosure closure so my object is not initialized right away. But how can I solve the warning ?
Here's the code:
struct MyView: View {
@StateObject var viewModel = MyViewModel()
var body: some View {
VStack(spacing: 0) {
switch viewModel.state { // warning hits here
case .initial, .loading:
shimmer
.padding(.horizontal, 16)
case .success, .finished, .refreshing:
content
.padding(.horizontal, 16)
case .failure(let error):
ErrorView(error: error)
}
}
// ...
}
...
The snippet looks correct to me. Check if MyView receives a different id or is always recreated as a brand new view, which would cause the cached viewModel to be discarded (same would apply to a State wrapped value).
The @autoclosure part of StateObject makes the wrapper lazy and what prevents MyViewModel() to be executed over and over again, that is not what's causing your issue.
I meant that you “might“ be using id up the view hierarchy. If the id changes, then the view is reconstructed (don‘t confuse this with re-intialization), the cached data is discarded and you get a new set.
Re-initialization happens a lot in SwiftUI, and that‘s by design, but things like State and StateObject will store the value internally and restore it after the view was re-intialized. I personally wish that State was a bit more like StateObject, but unfortunately State is not lazy.