具有动态数组的 SwiftUI 多个选择器,索引超出范围错误
Posted
技术标签:
【中文标题】具有动态数组的 SwiftUI 多个选择器,索引超出范围错误【英文标题】:SwiftUI multiple pickers with dynamic arrays, index out of range error 【发布时间】:2020-08-03 19:16:36 【问题描述】:原始问题:我需要加载 3 个选择器,每个后续选择器的选择选项取决于它之前的选择器 - 并且每个后续数组都基于 (a) 先前选择和 (b) a大约 500 个对象的数据库。
选择器一工作正常,因为它的选项数组没有改变 并且仅依赖于数据文件。 选择器 2 工作正常,因为它严格按照 选择器 1。 然而,选择器 3 需要知道选择器 2 中的选择才能按顺序 生成它的选项。但是选择器 2 中的选项是根据选择器 1 中的选择动态生成的。因此,如果选择器 1 中的选择发生变化,使得选择器 2 中的(选择)数组的长度小于提供给选择器 3 的特定选择,则程序会因超出范围错误而崩溃。我完全理解为什么会发生崩溃(很清楚)。但似乎我在这里试图实现的目标相当普遍,应该有一个解决方案。我能找到的所有解决方案都处理可以提前修复选择器数组的实例(例如反复出现的 Country/City 示例)。
【问题讨论】:
这里没有直接的解决方案。您需要避免在错误索引处访问数组的情况。我建议有一个视图模型,其中每个选择器都需要在每次更改时正确填充@Published
数组。然后遍历数组,而不是索引:ForEach(models, id: \.self) ...
。基本上,设计你的模型,就好像没有选择器一样——只有一些改变选择的功能,并使 起作用;然后将其连接到选择器
感谢您的回复。你说的很有道理,尽管我在尝试实施它时遇到了最困难的时间。我可以创建空的@Published 数组,但我认为我想要的是工作的、更新的填充数组。但是,每当我尝试(在我的视图之外工作)通过调用我的函数来用数据填充数组时,我最终都会遇到关于在初始化之前使用 self 的编译器错误。我对 swift 很陌生,我真的不知道何时何地可以调用函数:我不能在课堂上这样做,但我不想在视图中这样做。这让我不知所措。
【参考方案1】:
在这里回答我自己的问题,并更新,因为我找到了一个更简单、更稳定的解决方案。该解决方案需要许多元素:
-
正如 New Dev 的有益建议,数据结构必须是
构造使得拾取器元素相互连接。
我最初派生了三个不同的独立数组。当一个
动态更新,没有任何东西可以跟踪他们的关系。所以我创建了一个数据结构,其中较高的选择(例如品牌)包含较低的选择(例如型号和年份)。
此外,数组的索引不能直接绑定到每个选择器中的选项。这里的解决方案是按照这里的答案创建第二组绑定 Ints:SwiftUI Picker onChange or equivalent?
这是最终结果,我现在已经进行了广泛的测试,它完全稳定。
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)
【讨论】:
以上是关于具有动态数组的 SwiftUI 多个选择器,索引超出范围错误的主要内容,如果未能解决你的问题,请参考以下文章
来自先前选择器的选择器值 - CoreData/SwiftUI