swiftUi :一个屏幕上有 2 个选取器 - 应用程序崩溃,"索引超出范围"



当我尝试将 2 个行数不同的 piker 放在屏幕上与不同的观察者时。 如果我在第二行中不存在的一个数字中选择, 当我移动到第二个选择器应用程序崩溃并显示以下消息时: "致命错误:索引超出范围">

public enum kTrackType {
case audio
case text
}
class kTrack: NSObject, Identifiable {
public var id = UUID()
public var trakcId: String
public var title: String
public var type: kTrackType
public init(id: String, title: String, type: kTrackType) {
self.trakcId = id
self.title = title
self.type = type
}
}

这是主要结构:

struct SelectedAudioAndSubtileView: View {
let geometry: GeometryProxy
@State var subtitlesList = [kTrack(id: "t0", title: "None", type: kTrackType.text),
kTrack(id: "t1", title: "En", type: kTrackType.text),
kTrack(id: "t2", title: "Rus", type: kTrackType.text),
kTrack(id: "t3", title: "Spn", type: kTrackType.text)]
@State var multiAudioList =  [kTrack(id: "s0", title: "En", type: kTrackType.audio),
kTrack(id: "s1", title: "Rus", type: kTrackType.audio)]
@Binding var showSubtitlesPicker: Bool
@State private var selectedAudioPicker: Int = 0
@State private var selectedSubtitlePicker: Int = 0
@State private var selectedType = 0
var body: some View {
VStack {
Picker(selection: $selectedType, label: EmptyView()) {
Text("Audio").tag(0)
Text("Subtitle").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
Text(self.selectedType == 0 ? "Select Audio" : "Select Subtitle")
Divider()
if selectedType == 0 {
Picker(selection: self.$selectedAudioPicker, label: Text("")) {
ForEach(self.multiAudioList, id: .id){ name in
Text(name.title)
}
}
} else {
Picker(selection: self.$selectedSubtitlePicker, label: Text("")) {
ForEach(self.subtitlesList, id: .id){ name in
Text(name.title)
}
}
}
Divider()
}
.background(Color(#colorLiteral(red: 0.9686274529, green: 0.78039217, blue: 0.3450980484, alpha: 1)))
.offset(y: geometry.size.height - 330)
}

重新检查后,如果您在 2 个拣选器中有相同的行,也会发生崩溃!

情况如下:

a(selectedValue应与标签值匹配,因此在ForEach中,最好使用index而不是id,以便您可以为每个项目添加标签。

b(ForEach结构很复杂,通常要重复使用以提高效率。因此,为了强制刷新它,可以将id()修饰符添加到额外的ForEach结构中。必须有一个没有idForEach提供真正的底层数据层。

if selectedType == 0 {
Picker (selection: self.$selectedAudioPicker, label: Text("")) {
ForEach(0..<self.multiAudioList.count){ index in
Text(self.multiAudioList[index].title).tag(index)
}
}
} else if  selectedType == 1 {
Picker(selection: self.$selectedSubtitlePicker, label: Text("")) {
ForEach(0..<self.subtitlesList.count){ index in
Text(self.subtitlesList[index].title).tag(index)
}.id(0)
}
}

最新更新