SwiftUI 如何不在列表中复制 ViewModel
Posted
技术标签:
【中文标题】SwiftUI 如何不在列表中复制 ViewModel【英文标题】:SwiftUI How to not duplicate ViewModel in List 【发布时间】:2022-01-17 05:56:45 【问题描述】:我有简单的 2 屏幕应用程序。第一个屏幕是List
,第二个是详细屏幕。
显然我不需要 20 个详细的屏幕,与 List
中的项目数相同,但只有一个。
我需要将所选项目作为参数传递给详细屏幕的ViewModel
。我知道有两个选项可以实现这一点:
-
为每个
NavigationLink
创建新的ViewModel(selectededItem: Item)
通过EnvironmentObject
传递它,但这也是一个不好的解决方案,因为首先我需要一些类似viewModel.selectedItem = item
的方法
我目前的实现。它复制了视图模型,还有一个非常重要的问题是 - SwiftUI 是否为每个导航链接以及视图模型创建新视图的副本?
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)
【问题讨论】:
欢迎来到 Stack Overflow!请拨打tour 并查看:How do I ask a good question? 和How to create a Minimal, Reproducible Example。确保显示您的ProductsListView
是什么。您不需要ProductsListBuilder
。我也会通过Apple's SwiftUI Tutorials 和Stanford's CS193P。
【参考方案1】:
在这种情况下你可以使用LazyView
:
struct LazyView<Content: View>: View
let build: () -> Content
init(_ build: @autoclosure @escaping () -> Content)
self.build = build
var body: Content
build()
它使build
仅在导航链接实际打开时被调用:
NavigationLink(destination: LazyView(
ProductsListBuilder.build(id: subCategory.id ?? -1)
), label:
Text(subCategory.title ?? "no name")
)
【讨论】:
太棒了!!!非常简单优雅的解决方案,谢谢。以上是关于SwiftUI 如何不在列表中复制 ViewModel的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:如果不在列表中,NavigationLink 不起作用
如何将不在根层次结构中的 SwiftUI 视图呈现为 UIImage?
如何在 swiftui 中弹出到 TabView 应用程序中的特定视图。我也使用了 StackNavigation 但不在 swiftui 中工作