SwiftUI NavigationStack视图/ViewModel重复创建问题求助
问题根源
你当前代码里WelcomeViewModel重复实例化的核心原因是:在RootView的body中直接通过.init()创建实例并传给WelcomeView。SwiftUI会在视图树重绘(比如导航路径变化、状态更新)时重新执行body内的代码,这就导致每次重绘都会生成新的WelcomeViewModel对象。你添加的.id("Welcome")只作用于WelcomeView本身的身份识别,无法阻止参数里的ViewModel被重复初始化。
解决方案
把WelcomeViewModel的实例交由@StateObject管理,@StateObject会确保对象在视图的整个生命周期内只初始化一次,不会因视图重绘而重新创建。
修改后的关键代码
- 更新RootView:
struct RootView: View { @StateObject var router = Router.shared // 用@StateObject持有WelcomeViewModel,保证单实例 @StateObject private var welcomeVM = WelcomeViewModel(title: "Welcome", router: Router.shared) var body: some View { NavigationStack(path: $router.steps) { // 直接传入已初始化的welcomeVM,而非在参数内新建 WelcomeView(viewModel: welcomeVM) .navigationDestination(for: Step.self) { step in switch step { case .page1: StepView(viewModel: Step1ViewModel(step: step, router: router)) case .page2: StepView(viewModel: Step2ViewModel(step: step, router: router)) case .page3: StepView(viewModel: Step3ViewModel(step: step, router: router)) } } } } }
- 额外优化(可选):
如果想让Step对应的ViewModel也避免重复创建,可以调整为在StepView内部基于step和router作为标识,结合@StateObject的工厂方法创建:
struct StepView: View { let step: Step let router: Router // 根据step和router生成唯一的ViewModel实例 @StateObject private var viewModel: BaseStepViewModel { switch step { case .page1: return Step1ViewModel(step: step, router: router) case .page2: return Step2ViewModel(step: step, router: router) case .page3: return Step3ViewModel(step: step, router: router) } } var body: some View { Button { viewModel.shopNextPage() } label: { Text(viewModel.step.rawValue) } } }
此时navigationDestination只需传入step和router:
.navigationDestination(for: Step.self) { step in StepView(step: step, router: router) }
效果验证
修改后运行代码,控制台只会打印一次Created welcome view,WelcomeViewModel不会再被重复实例化。
内容的提问来源于stack exchange,提问作者Artem N0t2Day Kedrov
相关产品推荐
相关产品推荐

