How can I initialize View Again in SwiftUI?
Solution 1:
You just need to defer your destination creation in your builder, and the @ViewBuilder
is a good instrument for this.
It can be used the following wrapper for to create real destination only in when body
will be rendered (ie. explicitly in time of navigation clicked in your case)
Tested with Xcode 11.4 / iOS 13.4
struct DeferView<Content: View>: View {
let content: () -> Content
init(@ViewBuilder _ content: @escaping () -> Content) {
self.content = content
}
var body: some View {
content() // << everything is created here
}
}
and now your builder
final class DetailViewBuilder {
static func make(object: Something) -> some View {
DeferView {
DetailView(viewModel: DetailViewModel(object: object))
}
}
}
Solution 2:
SwiftUI initialises NavigationView
links eagerly, so you can't rely on their initialiser to run every time. If you write a custom init() for DetailView
init(viewModel: DetailViewModel) {
self.viewModel = viewModel
print("Initialising \(self)")
}
you'll see the line print out for every navigation link when your FirstView loads.
Depending on what you want to do you could implement a .onAppear {}
closure on the DetailView which will change the data when the view appears. It's a little tricky to try to offer implementation examples since I'm unsure what your goal here is specifically.
There's some interesting discussion of this at: https://www.notion.so/Lazy-Loading-Data-with-SwiftUI-and-Combine-70546ec6aca3481f80d104cd1f10a31a
Do any of the suggestions here look like they could be relevant to what you're trying to do?