I have simple 2 screens app. First screen is the List
, second is detailed screen.
It's obvious I don't need 20 detailed screens, same as number of items in the List
, but only one.
I need pass selected item as parameter to ViewModel
of the detailed screen. I know two options implement this:
- Create for each
NavigationLink
newViewModel(selectededItem: Item)
- Pass it through
EnvironmentObject
, but it's also bad solution, because first I need some how do likeviewModel.selectedItem = item
My current implementation. It duplicates view models, also very important question is - does SwiftUI create copy of new view for each navigation link as well as view model?
List(viewModel.state.subCategory) { subCategory in
HStack {
NavigationLink(destination: {
ProductsListBuilder.build(id: subCategory.id ?? -1)
}, label: {
Text(subCategory.title ?? "no name")
})
}
}
class ProductsListBuilder {
static func build(id: Int) -> some View {
let viewModel = ProductsViewModel(dataFetcher: RemoteDataProviderImpl.shared, productId: id)
return ProductsListView(viewModel: viewModel)
}
}
CodePudding user response:
In such cases you can use LazyView
:
struct LazyView<Content: View>: View {
let build: () -> Content
init(_ build: @autoclosure @escaping () -> Content) {
self.build = build
}
var body: Content {
build()
}
}
It makes build
to only be called when the navigation link is actually opened:
NavigationLink(destination: LazyView(
ProductsListBuilder.build(id: subCategory.id ?? -1)
), label: {
Text(subCategory.title ?? "no name")
})