模态NavigationStack首次入栈无动画问题求助
当通过.sheet模态展示包含NavigationStack的视图时,首次点击按钮推入栈内视图没有过渡动画,但后续的推入或返回操作动画表现正常。经排查,该问题与将导航路径path放在ViewModel中用@Published修饰有关,若将path改为视图内的@State属性则动画正常。需要在保留ViewModel管理路径的前提下解决此问题。

解决方案
核心问题出在sheet弹出初期,ViewModel的@Published状态更新与NavigationStack的初始化时机不匹配,导致首次动画未被触发。以下两种方案可解决:
方案1:延迟绑定ViewModel路径
在View1中先使用本地@State临时托管路径,待sheet完全展示后再切换到ViewModel的路径,确保NavigationStack初始化完成后再响应状态变化:
struct View1: View { @ObservedObject var viewModel: ViewModel @State private var localPath: [Path] = [] @State private var isReady = false var body: some View { NavigationStack(path: isReady ? $viewModel.path : $localPath) { VStack { Text("View 1").font(.largeTitle) Button("Goto 2") { viewModel.next() } } .navigationDestination(for: Path.self) { view in switch view { case .view2: View2(viewModel: viewModel) case .view3: View3() default: EmptyView() } } } .onAppear { // 延迟绑定,确保sheet完全加载 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { isReady = true localPath = viewModel.path } } } }
方案2:延迟ViewModel路径更新
在ViewModel的next方法中,用DispatchQueue.main.async延迟路径更新,给UI足够的初始化时间:
class ViewModel: ObservableObject { @Published var path: [Path] = [] func next() { DispatchQueue.main.async { self.path.append(self.path.count == 1 ? .view3 : .view2) } } }
原理说明
方案1通过延迟绑定ViewModel的路径,避免了NavigationStack在初始化阶段就接收状态更新;方案2则是让路径更新操作等待UI初始化完成,确保动画系统能正确捕获状态变化并触发过渡动画。两种方案都能保留ViewModel管理导航路径的逻辑,同时解决首次无动画的问题。
内容的提问来源于stack exchange,提问作者drekka
相关产品推荐
相关产品推荐

