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

NavigationStack内NavigationLink无法激活问题排查

问题排查与修复

核心错误原因

你遇到的NavigationLink试图传递“User”类型的值,但链接位置没有可见的匹配navigationDestination声明错误,本质是**navigationDestination的放置层级不正确**:
你把User类型的导航目标声明放在了List的修饰符中,而SwiftUI要求navigationDestination必须属于NavigationStack的直接子视图层级(或其直接后代的根视图修饰符),否则NavigationStack无法识别到对应的目标映射规则。

修复步骤

1. 调整navigationDestination的位置

将SubsubTestView中原本挂在List上的navigationDestination,移到视图的根容器(VStack)的修饰符中,确保NavigationStack能捕获到这个目标声明:

struct SubsubTestView: View {
    @EnvironmentObject var envObj: EnvObj
    @StateObject var vm: VM
    
    var body: some View {
        VStack {
            List(self.vm.envObj.users) { user in
                NavigationLink(value: user) {
                    Text(user.name)
                }
            }
        }
        // 移到VStack的修饰符中,而非List
        .navigationDestination(for: User.self) { user in
            DetailView(vm: VMD(envObj: envObj, selectedUser: user))
        }
    }
}

2. 可选优化(提升代码健壮性)

  • DetailView中TextField的安全绑定:
    原代码中自定义的??运算符虽然能工作,但可以用更直观的可选绑定避免默认空User的创建:

    struct DetailView: View {
        @StateObject var vm: VMD
        
        var body: some View {
            VStack {
                if let selectedUser = $vm.selectedUser {
                    TextField("姓名: ", text: selectedUser.name)
                } else {
                    Text("未选中用户")
                }
                Text(self.vm.selectedUser?.name ?? "无")
                Button("提交", action: vm.submit)
            }
        }
    }
    
  • VMD中submit方法的规范写法:
    原lazy var写法可以替换为普通方法,更符合Swift编码习惯:

    class VMD: ObservableObject {
        var envObj: EnvObj = .init()
        @Published var selectedUser: User?
        
        init(envObj: EnvObj, selectedUser: User? = nil) {
            self.envObj = envObj
            self.selectedUser = selectedUser
        }
        
        // 替换原来的lazy var为普通方法
        func submit() {
            if let user = self.selectedUser {
                self.update(user: user)
            }
        }
        
        func update(user: User) {
            self.envObj.users = self.envObj.users.map {
                $0 == user ? user : $0
            }
        }
    }
    

完整修复后的代码

import SwiftUI

class EnvObj: ObservableObject {
    @Published var users = [User(name: "a"), User(name: "b"), User(name: "c")]
}

struct User: Hashable, Identifiable, Equatable {
    var id = UUID()
    var name = ""
    
    static func == (lhs: User, rhs: User) -> Bool{
        return lhs.id == rhs.id
    }
}

struct ContentView: View {
    @EnvironmentObject var envObj: EnvObj
    @State var moveToSubsub = false
    
    var body: some View {
        NavigationStack {
            Button("跳转到Subsub") {
                moveToSubsub = true
            }
            .navigationDestination(isPresented: $moveToSubsub) {
                SubsubTestView(vm: VM(envObj: envObj))
            }
        }
    }
}

struct SubsubTestView: View {
    @EnvironmentObject var envObj: EnvObj
    @StateObject var vm: VM
    
    var body: some View {
        VStack {
            List(self.vm.envObj.users) { user in
                NavigationLink(value: user) {
                    Text(user.name)
                }
            }
        }
        .navigationDestination(for: User.self) { user in
            DetailView(vm: VMD(envObj: envObj, selectedUser: user))
        }
    }
}

class VM: ObservableObject {
    var envObj: EnvObj = .init()
    
    init(envObj: EnvObj) {
        self.envObj = envObj
    }
}

struct DetailView: View {
    @StateObject var vm: VMD
    
    var body: some View {
        VStack {
            if let selectedUser = $vm.selectedUser {
                TextField("姓名: ", text: selectedUser.name)
            } else {
                Text("未选中用户")
            }
            Text(vm.selectedUser?.name ?? "无")
            Button("提交", action: vm.submit)
        }
    }
}

class VMD: ObservableObject {
    var envObj: EnvObj = .init()
    @Published var selectedUser: User?
    
    init(envObj: EnvObj, selectedUser: User? = nil) {
        self.envObj = envObj
        self.selectedUser = selectedUser
    }
    
    func submit() {
        if let user = selectedUser {
            update(user: user)
        }
    }
    
    func update(user: User) {
        envObj.users = envObj.users.map {
            $0 == user ? user : $0
        }
    }
}

func ??<T>(binding: Binding<T?>, fallback: T) -> Binding<T> {
    return Binding(get: {
        binding.wrappedValue ?? fallback
    }, set: {
        binding.wrappedValue = $0
    })
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:40:34