You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NavigationStack搭配@Observable连续导航失效问题排查

问题原因分析

你的代码核心问题在于子视图模型(Class1、Class2)中的path是mainClass.path的副本,而非绑定引用。当你在View1里调用model.path.append(...)时,修改的只是Class1实例里的局部数组,并没有更新NavigationStack绑定的mainClass.path,所以SwiftUI无法感知到路径变化,自然不会触发后续导航。

解决方案

不需要使用EnvironmentObject,只需要让子视图直接操作主模型的path绑定即可。具体调整如下:

  1. 移除Class1、Class2中多余的path属性,因为它们不需要自己维护路径,直接使用主模型的路径绑定。
  2. 在创建子视图时,将主模型的实例传递下去(借助@Bindable保持响应式绑定)。

修改后的完整代码:

import SwiftUI

@Observable @MainActor
final class MainClass {
    public enum Destination: Hashable {
        case view1
        case view2
    }
    
    var path: [Destination] = []
}

struct View1: View {
    @Bindable var mainModel: MainClass
    var body: some View {
        Button("Go to View 2") {
            mainModel.path.append(.view2)
        }
    }
}

struct View2: View {
    var body: some View {
        Text("View 2")
    }
}

@MainActor
struct ContentView: View {
    @Bindable var mainClass = MainClass()
    
    var body: some View {
        NavigationStack(path: $mainClass.path) {
            Button("Go to View 1") {
                mainClass.path.append(.view1)
            }
            .padding()
            .navigationDestination(for: MainClass.Destination.self) { destination in
                switch destination {
                case .view1:
                    View1(mainModel: mainClass)
                case .view2:
                    View2()
                }
            }
        }
    }
}

#Preview {
    ContentView()
}
关键调整说明
  • 简化MainClass.Destination枚举,不再携带子模型(子视图不需要独立维护路径,直接依赖主模型的路径即可)。
  • View1直接接收MainClass的绑定实例,点击按钮时直接修改主模型的path,确保NavigationStack能实时感知路径变化并触发导航。
  • 移除了Class1、Class2中不必要的Hashable实现和path属性,大幅简化代码结构。

如果你的子视图确实需要独立业务模型,可以将模型和主路径绑定分开传递,示例如下:

// 带业务数据的子模型
@Observable @MainActor
final class Class1 {
    var someData: String
    init(someData: String) {
        self.someData = someData
    }
}

// 调整后的View1
struct View1: View {
    @Bindable var model: Class1
    @Bindable var mainModel: MainClass
    var body: some View {
        VStack {
            Text("View1 业务数据: \(model.someData)")
            Button("Go to View 2") {
                mainModel.path.append(.view2)
            }
        }
    }
}

// 在导航目标中传递模型和主绑定
case .view1:
    View1(model: Class1(someData: "测试数据"), mainModel: mainClass)

这种方式既保留了子视图的业务模型,又能正确触发导航,同时满足不使用EnvironmentObject的要求。

内容的提问来源于stack exchange,提问作者miltenkot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:26:08