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

如何在NavigationStack.navigationDestination中向子视图传递Binding

问题核心原因

你写的代码有两个本质问题,直接导致无法传入Binding、修改无法同步:

  • 硬编码的0 ..< 5是临时常量区间,没有被任何状态属性持有,本身不存在可双向绑定的引用
  • navigationDestination(for:)闭包中拿到的number是值类型的临时拷贝,不是原数据的引用,哪怕给它加$前缀,拿到的也是临时值的绑定,修改后不会同步回父列表
实现方案

方案1:传标识取绑定(推荐,适配NavigationStack全特性)

这是最符合新版NavigationStack设计逻辑的写法,支持导航栈状态恢复、深链接跳转,不会出现绑定失效问题。
核心逻辑是导航时只传递元素的唯一标识(优先用业务ID,简单Demo可以用索引),在navigationDestination闭包里从父视图持有的状态数据源中,取出对应元素的双向绑定传给子视图。
实际业务开发中不要用索引作为导航标识,优先使用数据模型自带的唯一业务ID,避免数组增删后索引错位导致绑定错误。

完整可运行代码:

import SwiftUI

struct ParentListView: View {
    // 列表数据源作为唯一真相源,存在父视图State中
    @State private var numbers = Array(0..<5)
    
    var body: some View {
        NavigationStack {
            List {
                // 遍历时传递元素索引作为导航匹配值
                ForEach(Array(numbers.enumerated()), id: \.offset) { index, number in
                    NavigationLink(value: index) {
                        Text("\(number)")
                    }
                }
            }
            .navigationDestination(for: Int.self) { index in
                // 从State数组中取对应位置元素的Binding传给子视图
                ChildDetailView(number: $numbers[index])
            }
        }
    }
}

struct ChildDetailView: View {
    @Binding var number: Int
    var body: some View {
        VStack {
            Text("\(number)")
            Button {
                number += 10
            } label: {
                Text("Add 10")
            }
        }
    }
}

方案2:NavigationLink直接传绑定(仅适合简单场景)

如果你的导航逻辑非常简单,不需要状态恢复、深链接能力,可以直接在ForEach中遍历数据源的绑定,在NavigationLink的目标闭包中直接把绑定传给详情页,不需要通过navigationDestination做类型匹配:

import SwiftUI

struct ParentListView: View {
    @State private var numbers = Array(0..<5)
    
    var body: some View {
        NavigationStack {
            List {
                // 直接遍历数组的投影值(Binding序列)
                ForEach($numbers, id: \.self) { $number in
                    NavigationLink {
                        ChildDetailView(number: $number)
                    } label: {
                        Text("\(number)")
                    }
                }
            }
        }
    }
}

// ChildDetailView代码和之前一致,无需修改

注意:方案2中Binding是无法被NavigationStack序列化的,当应用被系统后台回收、通过深链接跳转页面时,会出现找不到绑定、页面崩溃的问题,生产环境优先选择方案1。

内容的提问来源于stack exchange,提问作者P. Protas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:12:28