如何通过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
相关产品推荐
相关产品推荐

