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

如何通过NavigationLink将ForEach变量传入Binding类型参数

问题:无法将遍历的整数传入@Binding类型参数

相关代码

SelectorView代码

struct SelectorView: View {

    let levelamt: Int = 50
    var next: Int = 20
    let columns: [GridItem] = [GridItem(), GridItem(), GridItem()]

    var body: some View {
        NavigationStack {
            ZStack {
                Color(red: 0, green: 0, blue: 0).ignoresSafeArea()
                LazyVGrid(columns: columns) { 
                    ForEach(1..<next, id: \.self) { x in
                        NavigationLink(destination: GameView(level: self.x), label: {
                            ZStack {
                                Image("Fragment")
                                    .resizable()
                                    .frame(width: 125, height: 125)
                                    .scaledToFit()
                                Text(String(x))
                                    .font(.system(size: 50, design: .monospaced))
                                    .fontWeight(.bold)
                                    .foregroundColor(Color.white)
                                }
                            })
                        }
                    }
                }
            }
        }
    }
}

GameView代码

struct GameView: View {

    @Binding var level: Int

    var body: some View {

        Text("hello world")

    }
}

报错原理

  • @Binding的核心是双向绑定,它要求传入的是可读写的绑定对象(比如@State/@Published属性的投影值$xxx),而遍历范围得到的x是普通的Int值类型常量,没有对应的可绑定数据源,直接传递必然报错。
  • 因为遍历的是范围1..<next而非数组,常规的数组元素绑定方案无法直接套用,这也是你之前看到的解决方案无效的原因。

解决方法

根据GameView的实际需求选择对应方案:

方案1:GameView仅需使用level值,无需修改

如果GameView只是展示或使用level的值,不需要修改并同步回SelectorView,直接把GameView的@Binding改为普通常量即可:

struct GameView: View {
    // 替换@Binding为普通常量
    let level: Int

    var body: some View {
        Text("hello world, level: \(level)")
    }
}

此时SelectorView中直接传递x即可:GameView(level: x)

方案2:GameView需要修改level并同步回SelectorView

如果确实需要双向绑定,需要给SelectorView添加可绑定的数据源,比如用@State数组存储所有level值,再通过索引传递绑定:

struct SelectorView: View {
    let levelamt: Int = 50
    var next: Int = 20
    let columns: [GridItem] = [GridItem(), GridItem(), GridItem()]
    // 初始化存储所有level的数组,对应遍历范围1..<next
    @State private var levels: [Int] = Array(1..<20)

    var body: some View {
        NavigationStack {
            ZStack {
                Color(red: 0, green: 0, blue: 0).ignoresSafeArea()
                LazyVGrid(columns: columns) {
                    // 遍历数组的索引和元素,通过索引传递绑定
                    ForEach(Array(levels.enumerated()), id: \.element) { index, level in
                        NavigationLink(destination: GameView(level: $levels[index]), label: {
                            ZStack {
                                Image("Fragment")
                                    .resizable()
                                    .frame(width: 125, height: 125)
                                    .scaledToFit()
                                Text(String(level))
                                    .font(.system(size: 50, design: .monospaced))
                                    .fontWeight(.bold)
                                    .foregroundColor(Color.white)
                            }
                        })
                    }
                }
            }
        }
    }
}

这样GameView中修改level的值时,会同步更新SelectorView的levels数组,实现双向绑定效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:00:12