我在下面的视图中实例化了一行按钮,我打算使它们成为可选择的(一次仅一个)。
//@State var currentSelectedIndex = 0
//var rooms: [Room]
ScrollView(.horizontal, showsIndicators: false, content: {
HStack {
ForEach(rooms.indices) { roomIndex in
Button(action: {
currentSelectedIndex = roomIndex
}) {
UserSelectionIcon(room: rooms[roomIndex], selected: roomIndex == currentSelectedIndex)
.padding(10)
}
}
}
})
选择一个时,它周围应显示一个蓝色圆圈。这是我上面引用的UserSelectionIcon对象中的行应执行的操作;
//@State var selected: Bool = false
Circle()
.strokeBorder(selected ? Color.blue.opacity(0.7) : Color.clear, lineWidth: 2)
此行确实有效,因为选择了第一个索引并显示蓝色圆圈。但是,单击任何按钮都不会显示它们周围的蓝色圆圈。 currentSelectedIndex变量正在按预期进行更新。
答案 0 :(得分:1)
在UserSelectionIcon
中,您必须使用Bindings
来访问currentSelectedIndex
而不是States
,因为如果更改值,States
不会更新在另一个视图中。
因此,您必须在Bool
视图中安全地将Binding
“选择”为UserSelectionIcon
。更改此:
@State var selected: Bool = false
对此:
@Binding var selected: Bool
并不仅仅是重构此调用:
UserSelectionIcon(room: rooms[roomIndex], selected: roomIndex == currentSelectedIndex)
对此:
UserSelectionIcon(room: rooms[roomIndex], selected: Binding(get: { roomIndex == currentSelectedIndex }, set: {_,_ in }))
现在,您将两个索引的比较包装到一个绑定中,该绑定将始终代表两个索引的最新比较。如果只传递比较,则它就像一个一次性值,如果其中一个索引被更新,它将不会刷新它的结果。但是现在,当您选择应为笔触边框选择哪种颜色时,每次访问绑定时都会重新评估比较。
替代解决方案:
您应该重构它:
UserSelectionIcon(room: rooms[roomIndex], selected: roomIndex == currentSelectedIndex)
对此(传递State
变量):
UserSelectionIcon(room: rooms[roomIndex], currentSelectedIndex: currentSelectedIndex)
,在您的UserSelectionIcon
中,您应该重构此行:
@State var selected: Bool = false
收件人:
@Binding var currentSelectedIndex: Bool
,每个图标应保存其索引本身,以便以后进行比较:
var roomIndex: Int
然后您可以在显示边框时比较这两个索引。
.strokeBorder(currentSelectedIndex == roomIndex ? Color.blue.opacity(0.7) : Color.clear, lineWidth: 2)