Множественные сборщики SwiftUI с массивами Dynami c, ошибка индекса вне диапазона - PullRequest
2 голосов
/ 03 августа 2020

Исходная проблема: мне нужно загрузить 3 средства выбора, причем выбор каждого последующего средства выбора зависит от предшествующих - и с каждым из последующих массивов, генерируемых динамически на основе (а) предыдущих вариантов и (б) база данных из примерно 500 объектов.

  • Первое средство выбора работает нормально, потому что его массив параметров не изменяется и зависит только от файла данных.
  • Средство выбора два отлично работает, потому что оно строго обновляется в соответствии с средством выбора 1.
  • Средство выбора три, однако, должно знать выбор в средстве выбора 2, чтобы сгенерировать свои параметры. Но параметры в средстве выбора 2 генерируются динамически из выбора в средстве выбора 1.

Следовательно, если выбор в средстве выбора 1 изменяется так, что длина массива (вариантов) в средстве выбора 2 меньше чем указанный c выбор передается в средство выбора 3, программа вылетает с ошибкой вне допустимого диапазона. Совершенно понимаю, почему кра sh происходит (понятно). Но похоже, что то, чего я здесь пытаюсь достичь, будет довольно обычным явлением и должно быть решение. Все решения, которые я мог найти, относятся к случаям, когда массивы сборщика могут быть исправлены заранее (например, пример страны / города, который повторяется постоянно).

1 Ответ

1 голос
/ 06 августа 2020

Отвечая на свой вопрос здесь, и обновляюсь, так как я нашел более простое и стабильное решение. Для решения требуется ряд элементов:

  1. Как услужливо предложила New Dev, структура данных должна быть построена так, чтобы элементы средства выбора были связаны друг с другом. Изначально я получил три отдельных массива. При динамическом обновлении нечего было отслеживать их отношения. Итак, я создал структуру данных, в которой более высокие варианты (например, бренды) содержали более низкие варианты (например, модели и годы).
  2. Кроме того, индексы для массивов не могут быть напрямую связаны с вариантами в каждом сборщике. Решение здесь - создать второй набор привязок Ints, следуя приведенному здесь ответу: SwiftUI Picker onChange или эквивалентный?

Вот окончательный результат, который я сейчас проверил. широко и полностью стабильно.

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 = $0
                    self.choice2 = 0
                    self.choice3 = 0
                })
        
        let chosenModel = Binding<Int>(get: {
                    return self.choice2
                }, set: {
                    self.choice2 = $0
                    self.choice3 = 0
                })
        
        let chosenYear = Binding<Int>(get: {
                    return self.choice3
                }, set: {
                    self.choice3 = $0
                })
    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)
                    }
                }
            }
        }
    }
...