带有动态数组的 SwiftUI 多个选择器,索引超出范围错误

SwiftUI multiple pickers with dynamic arrays, index out of range error

原始问题:我需要加载 3 个选择器,每个后续选择器的选择取决于它之前的选择 - 并且每个后续数组都是根据 (a) 先前的选择和 (b) 动态生成的) 一个包含大约 500 个对象的数据库。

因此,如果选择器 1 中的选择发生变化,导致选择器 2 中的(选择)数组的长度小于提供给选择器 3 的特定选择,程序会因超出范围错误而崩溃。我完全理解为什么会发生崩溃(很清楚)。但似乎我在这里尝试实现的目标是相当普遍的,并且应该有一个解决方案。我能找到的所有解决方案都处理可以提前修复选择器数组的情况(例如,重复出现的 Country/City 示例)。

在这里回答我自己的问题,并进行更新,因为我找到了一个更简单、更稳定的解决方案。该解决方案需要一些要素:

  1. 正如 New Dev 所建议的那样,数据结构必须是 构建使得选择器元素相互连接。 我最初派生了三个不同的数组。当一个 动态更新没有什么可以追踪他们的关系。所以我创建了一个数据结构,其中较高的选择(例如品牌)包含较低的选择(例如型号和年份)。
  2. 此外,数组的索引不能直接绑定到每个选择器中的选项。这里的解决方案是创建第二组绑定 Ints,遵循这里的答案:

这是最终结果,我现在已经对其进行了广泛的测试并且它完全稳定。

struct ContentView: View {

    @State private var brands: [Brand] = getBrands()
    @State private var choice1 = 0
    @State private var coice2 = 0
    @State private var choice3 = 0

    var body: some View {
        
        let chosenBrand = Binding<Int>(get: {
                    return self.choice1
                }, set: {
                    self.choice1 = [=10=]
                    self.choice2 = 0
                    self.choice3 = 0
                })
        
        let chosenModel = Binding<Int>(get: {
                    return self.choice2
                }, set: {
                    self.choice2 = [=10=]
                    self.choice3 = 0
                })
        
        let chosenYear = Binding<Int>(get: {
                    return self.choice3
                }, set: {
                    self.choice3 = [=10=]
                })
    return
        VStack {
            Picker(selection: chosenBrand, label: Text("Brand")) {
                ForEach(self.brands.indices, id: \.self) { index in
                    Text(self.brands[index].name).tag(index)
                    }
                }

            Picker(selection: chosenModel, label: Text("Model")) {
                ForEach(self.brands[choice1].models.indices, id: \.self) { index in
                    Text(self.brands[self.choice1].models[index].name).tag(index)
                    }
                }

            Picker(selection: chosenYear, label: Text("Year")) {
                ForEach(self.brands[choice1].models[choice2].years).indices, id: \.self) { index in
                    Text(self.brands[self.choice1].models[self.choice2].years[index].description).tag(index)
                    }
                }
            }
        }
    }