首页 > 解决方案 > 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 个选择器中有相同的行,也会发生崩溃!

标签: xcodeswiftuipicker

解决方案


这是情况:

a)selectedValue应该与标签值匹配,因此在 中ForEach,最好不要使用indexid这样您就可以为每个项目添加标签。

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

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

推荐阅读