Home > Net >  SwiftUI How to not duplicate ViewModel in List
SwiftUI How to not duplicate ViewModel in List

Time:12-15

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:

  1. Create for each NavigationLink new ViewModel(selectededItem: Item)
  2. Pass it through EnvironmentObject, but it's also bad solution, because first I need some how do like viewModel.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")
})
  • Related