简体   繁体   English

SwiftUI static 列出奇怪的重用行为

[英]SwiftUI static List weird reuse behavior

I'm facing a strange behavior using a static List in SwiftUI.我在使用 SwiftUI 中的 static 列表时遇到了一个奇怪的行为。 I can't determine if it's a SwiftUI bug or something I'm doing wrong.我无法确定这是 SwiftUI 错误还是我做错了什么。 I have a very simple List that looks like this:我有一个非常简单的列表,如下所示:

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

Each cell of the List looks like this: 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)
                }
            }
        })
    }

}

And finally, this is what a Segmentable object looks like:最后,这是一个Segmentable object 的样子:

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

}

When the SettingsView is loaded.加载SettingsView时。 everything looks fine.一切看起来都很好。 But as soon as I start scrolling, and some other cells are instantiated, there are some cell displayed, but not the proper ones.但是,一旦我开始滚动并实例化其他一些单元格,就会显示一些单元格,但不是正确的单元格。 Here is some screenshots and logs.这是一些截图和日志。

When the view is loaded, no scrolling, here is what the screen looks like:加载视图后,没有滚动,屏幕如下所示:

在此处输入图像描述

But, what I got on the console is pretty weird and doesn't follow the order of the SettingsPickerView written in the main View:但是,我在控制台上得到的东西很奇怪,并且不遵循在主视图中编写的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

The second section is ok and properly displayed:第二部分没问题并正确显示:

在此处输入图像描述

But the third section is completely broken:但是第三部分完全断了:

在此处输入图像描述

The third section displays its title properly, but display some of the data of the first section.第三部分正确显示其标题,但显示第一部分的一些数据。 I tried to add an identifier to the button in the cell because the issue looks like SwiftUI can't identify the proper data.我尝试向单元格中的按钮添加标识符,因为问题看起来像 SwiftUI 无法识别正确的数据。 But adding an identifier to the button broke the binding, and the checkbox don't change anymore.但是向按钮添加标识符会破坏绑定,并且复选框不再更改。

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

Does someone experienced something like this before?以前有人经历过这样的事情吗?

Thanks in advance for your help.在此先感谢您的帮助。

Here is fixed block of code (due to used indexes only List is confused and reuses rows, so solution is to make rows identifiable by items).这是固定的代码块(由于使用的索引只有 List 被混淆并重用行,因此解决方案是使行可被项目识别)。

Tested with Xcode 11.4用 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM