我在SwiftUI中使用静态列表面临着奇怪的行为。我无法确定这是SwiftUI错误还是我做错了什么。我有一个非常简单的清单,看起来像这样:
var body: some View {
List {
SettingsPickerView<TrigonometryUnit>(title: "Trigonometry Units", selection: $viewModel.trigonometryUnitIndex, items: TrigonometryUnit.allCases)
SettingsPickerView<DecimalSeparator>(title: "Decimal Separator", selection: $viewModel.decimalSeparatorIndex, items: DecimalSeparator.allCases)
SettingsPickerView<GroupingSeparator>(title: "Grouping Separator", selection: $viewModel.groupingSeparatorIndex, items: GroupingSeparator.allCases)
SettingsPickerView<ExponentSymbol>(title: "Exponent Symbol", selection: $viewModel.exponentSymbolIndex, items: ExponentSymbol.allCases)
}
}
列表的每个单元格如下所示:
struct SettingsPickerView<T: Segmentable>: View {
let title: String
@Binding var selection: Int
let items: [T]
var body: some View {
Section(header: Text(title)) {
ForEach(items.indices) { index in
self.cell(for: self.items[index], index: index)
}
}
}
private func cell(for item: T, index: Int) -> some View {
print(title, item.title, items.map({ $0.title }))
return Button(action: {
self.selection = index
}, label: {
HStack {
Text(item.title)
Spacer()
if index == self.selection {
Image(systemName: "checkmark")
.font(.headline)
.foregroundColor(.rpnCalculatorOrange)
}
}
})
}
}
最后,这是Segmentable
对象的样子:
enum GroupingSeparator: Int, CaseIterable {
case defaultSeparator
case space
case comma
}
extension GroupingSeparator: Segmentable {
var id: String {
switch self {
case .defaultSeparator:
return "groupingSeparator.default"
case .space:
return "groupingSeparator.space"
case .comma:
return "groupingSeparator.comma"
}
}
var title: String {
switch self {
case .defaultSeparator:
return "Default"
case .space:
return "Space"
case .comma:
return "Comma"
}
}
}
加载SettingsView
时。一切看起来都很好。但是,一旦我开始滚动并实例化了其他一些单元格,就会显示一些单元格,但不是正确的单元格。这是一些屏幕截图和日志。
加载视图后,不会滚动,这是屏幕的样子:
但是,我在控制台上看到的内容很奇怪,并且不遵循主视图中所写的SettingsPickerView
的顺序:
Trigonometry Units Radians ["Radians", "Degrees"] <-- Fine
Trigonometry Units Degrees ["Radians", "Degrees"] <-- Fine
Decimal Separator Default ["Default", "Dot", "Comma"] <-- Fine
Decimal Separator Default ["Default", "Dot", "Comma"] <-- Fine
Trigonometry Units Degrees ["Radians", "Degrees"] <-- Not expected. Should be Grouping Separator
Trigonometry Units Radians ["Radians", "Degrees"] <-- Not expected. Should be Grouping Separator
第二部分可以正常显示:
但是第三部分完全坏了:
第三部分正确显示其标题,但显示第一部分的某些数据。我试图将标识符添加到单元格中的按钮,因为该问题似乎SwiftUI无法识别正确的数据。但是向按钮添加标识符会破坏绑定,并且复选框不再更改。
private func cell(for item: T, index: Int) -> some View {
print(title, item.title, items.map({ $0.title }))
return Button(action: {
self.selection = index
}, label: {
HStack {
Text(item.title)
Spacer()
if index == self.selection {
Image(systemName: "checkmark")
.font(.headline)
.foregroundColor(.rpnCalculatorOrange)
}
}
})
.id(UUID().uuidString) // This solve the display issue but broke the binding.
}
有人以前经历过类似的事情吗?
预先感谢您的帮助。
答案 0 :(得分:1)
这是固定的代码块(由于仅使用了索引,列表才被混淆,因此可以重复使用行,因此解决方案是使行可以按项目标识)。
通过Xcode 11.4测试
struct PickerView<T: Segmentable>: View {
// ... other code here
var body: some View {
Section(header: Text(title)) {
// Corrected section construction !!
ForEach(Array(items.enumerated()), id: \.element.id) { index, _ in
self.cell(for: self.items[index], index: index)
}
}
}
// ... other code here