SwiftUI列表中使用@Binding传递引用:子视图未获取正确选中索引
问题分析与修改方案
问题原因
你的代码里ForEach的闭包参数名和父视图的@State变量selectedIndex重名了,这导致你在NavigationLink里传递的是循环中的临时索引值,而不是父视图的@State变量。更关键的是,这个临时变量不是可绑定类型,用$selectedIndex传递给子视图的@Binding参数是错误的,这就是子视图无法正确获取值的核心原因。
修改方案
根据你的实际需求,分两种场景给出修改代码:
场景1:子视图仅展示选中的索引(无需修改父视图状态)
这种情况不需要双向绑定,子视图直接接收普通数值即可,同时修正闭包参数名避免冲突:
import SwiftUI struct TestView: View { // 当前场景下这个@State变量没用,可以直接移除 // @State var selectedIndex: Int = 0 var body: some View { NavigationStack { VStack { List { Section(header: Text("Test")) { // 把闭包参数名改成index,避免和父视图变量重名 ForEach(0 ..< 5, id: \.self) { index in NavigationLink { // 直接传递循环的index值,不需要绑定 TestChildView(selectedIndex: index) } label: { Text(String(index)) } } } } } } } } struct TestChildView: View { // 用普通let接收展示值 let selectedIndex: Int var body: some View { VStack { Text(String(selectedIndex)) } } }
场景2:子视图需要修改父视图的selectedIndex(双向绑定)
如果需要子视图能反向修改父视图的选中索引,要确保传递父视图@State变量的绑定,同时在点击列表项时更新父视图的变量:
import SwiftUI struct TestView: View { @State var selectedIndex: Int = 0 var body: some View { NavigationStack { VStack { List { Section(header: Text("Test")) { ForEach(0 ..< 5, id: \.self) { index in NavigationLink { // 传递父视图selectedIndex的绑定 TestChildView(selectedIndex: $selectedIndex) } label: { Text(String(index)) } // 点击列表项时更新父视图的选中索引 .onTapGesture { selectedIndex = index } } } } } } } } struct TestChildView: View { @Binding var selectedIndex: Int var body: some View { VStack { Text(String(selectedIndex)) // 示例:子视图修改父视图的选中索引 Button("索引+1") { selectedIndex += 1 } } } }
内容的提问来源于stack exchange,提问作者Taka
相关产品推荐
相关产品推荐

