提问人:Mahin 提问时间:10/14/2023 最后编辑:Mahin 更新时间:10/14/2023 访问量:63
如何避免 Toggle 视图递归 onChange 调用 SwiftUI
How to avoid Toggle view recursive onChange call SwiftUI
问:
HStack{
ForEach($rs.newsCategoryCollection){ $category in
Toggle(category.id, isOn: $category.isSelected)
.toggleStyle(.button)
.onChange(of: category.isSelected) {value in
print("Changed")
if value{
rs.unselectOtherCategory(id: category.id)
print("Selected: \(category.id)")
viewModel.loadNews()
}else{
category.isSelected = true
print("Deselected: \(category.id)")
}
}
}
}
在这里,我尝试在水平视图中使用切换按钮。我希望将其用作一次仅选择一个类别的选择器。
因此,在用户选择任何一个类别后,应使用以下方法取消选择另一个类别:rs.unselectOtherCategory(id: category.id)
因此,我使用 onChange 通过跟踪值的变化来检测用户选择类别。但是,使用前面的方法取消选择所有其他类别会更改先前选择的类别的值,并再次调用 onChange。
当我使用 else 块来确保如果用户点击所选按钮并取消选择,则取消选择所有按钮时,else 块可以抵消它并选择唯一选定的按钮,问题变得更加完整。
如何避免这种重复的 onChange 调用。
我希望用户能够点击一个按钮并选择它,其他按钮将被取消选择。但是,如果用户点击已选择的按钮,则该按钮将保持选中状态。
答:
1赞
Sweeper
10/14/2023
#1
这看起来更像是一组 s。当您希望一次选择一件事时,不要使用 s。Picker
Toggle
Toggle
您可以将 s 更改为 s:Toggle
Button
HStack{
ForEach($rs.newsCategoryCollection){ $category in
Button(category.id) {
if !category.isSelected {
category.isSelected = true
rs.unselectOtherCategory(id: category.id)
viewModel.loadNews()
}
}
.padding(8)
.background(.accent.opacity(category.isSelected ? 0.1 : 0), in: RoundedRectangle(cornerRadius: 10))
}
}
也就是说,我建议使用 ,带有选择器样式,它看起来类似于一排按钮。Picker
.segmented
struct ContentView: View {
@State var rs = ...
@State var selectedCategory: NewsCategory.ID = "" // assuming NewsCategory.ID is a String
var body: some View {
Picker(selection: $selectedCategory) {
ForEach(rs.newsCategoryCollection){ category in
Text(category.id)
}
} label: {
}
.pickerStyle(.segmented)
.onChange(of: selectedCategory) {
viewModel.loadNews()
}
}
}
现在,您甚至不需要 中的属性。如果出于某种原因确实需要它,可以添加一个方法,例如isSelected
NewsCategory
selectCategory
rs
// selectCategory could be implemented as:
mutating func selectCategory(id: String) {
for i in newsCategoryCollection.indices {
if newsCategoryCollection[i].id != id {
newsCategoryCollection[i].isSelected = false
} else {
newsCategoryCollection[i].isSelected = true
}
}
}
然后将其调入 .onChange
评论
0赞
Mahin
10/14/2023
多谢。但我正在寻找一个 UI,其中将有水平对齐的选项,每个选项由每个选项分隔,例如在 youtube 应用程序的顶部,您可以在其中选择全部、音乐或其他内容。
0赞
Sweeper
10/14/2023
@Mahin看到编辑。也许你应该把 s 改成 s。Toggle
Button
0赞
Mahin
10/14/2023
美妙!我错过了一个非常简单的解决方案。多谢!
评论
Toggle
Picker
.segmented
onChange