SwiftUI MVVM中Toolbar内NavigationLink无法跳转视图问题排查
问题分析
你遇到的问题根源有两点:
- 直接在
ToolbarItem的闭包内创建NavigationLink和AddViewModel,每次视图刷新都会重新执行这段代码,导致AddViewModel重复初始化。 Toolbar的布局环境特殊,直接放置的NavigationLink交互触发逻辑会失效,无法正确触发页面跳转。
解决方案
方案一:绑定状态控制(兼容iOS 13+)
把NavigationLink移到主视图层级(不影响布局的背景层),用按钮控制绑定状态来触发跳转:
struct YourCurrentView: View { @State private var isAddViewPresented = false let viewModel: YourMainViewModel var body: some View { // 你的主视图内容 Text("Main View") .toolbar { ToolbarItem(placement: .confirmationAction) { Button(action: { isAddViewPresented = true }) { Text("") } .buttonStyle(AddButtonStyle()) } } .background( NavigationLink( "", destination: { let vm = viewModel.add() Add(viewModel: vm) }, isActive: $isAddViewPresented ) ) } }
方案二:使用navigationDestination(iOS 16+ 推荐)
iOS 16+提供了更简洁的跳转控制方式,无需手动管理NavigationLink的位置:
struct YourCurrentView: View { @State private var shouldNavigateToAdd = false let viewModel: YourMainViewModel var body: some View { // 你的主视图内容 Text("Main View") .toolbar { ToolbarItem(placement: .confirmationAction) { Button(action: { shouldNavigateToAdd = true }) { Text("") } .buttonStyle(AddButtonStyle()) } } .navigationDestination(isPresented: $shouldNavigateToAdd) { let vm = viewModel.add() Add(viewModel: vm) } } }
额外注意
避免在ToolbarItem的闭包内创建需要保持状态的对象(比如ViewModel),这个闭包会因视图刷新被频繁调用,导致重复初始化。应该把ViewModel的创建放在跳转触发的时机(比如按钮的action或navigationDestination的闭包内),这样只会在跳转执行时初始化一次。
内容的提问来源于stack exchange,提问作者J. Holliday
相关产品推荐
相关产品推荐

