ios - SwiftUI 静态列表奇怪的重用行为

标签 ios swift list swiftui

我在 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)
    }
}

List 的每个单元格如下所示:

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已加载。一切看起来都很好。但是,一旦我开始滚动并实例化其他一些单元格,就会显示一些单元格,但不是正确的单元格。这是一些截图和日志。

加载 View 后,没有滚动,屏幕如下所示:

enter image description here

但是,我在控制台上得到的东西很奇怪,并且不遵循 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

第二部分没问题并正确显示:

enter image description here

但是第三部分完全断了:

enter image description here

第三部分正确显示其标题,但显示第一部分的一些数据。我尝试向单元格中的按钮添加标识符,因为问题看起来像 SwiftUI 无法识别正确的数据。但是向按钮添加标识符会破坏绑定(bind),并且复选框不再更改。

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.
}

以前有人经历过这样的事情吗?

在此先感谢您的帮助。

最佳答案

这是固定的代码块(由于使用的索引只有 List 被混淆并重用行,因此解决方案是使行可被项目识别)。

使用 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

关于ios - SwiftUI 静态列表奇怪的重用行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62085215/

相关文章:

ios - 为什么这个变量是 "nil",即使我有一个 "if"语句检查它不是

ios - 核心数据实体管理器

ios - 每个拐角不同的拐角半径,扩展 TableView 单元格 View

ios - Swift:如何使用导航 Controller 重新加载表格

java - 按值复制 Java 列表

python - 检查列表中字符串内的字符串

ios - 拉动刷新 : data refresh is delayed

swift - 唯一约束不起作用

swift - 如果类型设置为相册,PHAssetCollection fetchAssetCollectionsContainingAsset 返回 nil

java - 根据与先前和后续项目的关系进行迭代时从列表中删除项目