swiftUi:在一个屏幕上有2个选择器-应用崩溃并显示“索引超出范围" [英] swiftUi : 2 Pickers on one screen - app crash with "Index out of range"

查看:66
本文介绍了swiftUi:在一个屏幕上有2个选择器-应用崩溃并显示“索引超出范围"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试用不同的观察者在屏幕上放置2个具有不同行数的桩子时. 如果我在第二行中不存在的行中选择一个, 当我转到第二个选择器应用程序时崩溃并显示以下消息: 致命错误:索引超出范围"

When I try to put 2 pikers with a different number of rows on-screen with different observers. if I select in one number of the row that not exists in the second, when I move to the second picker app crash with this message: "Fatal error: Index out of range"

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

After recheck, the crash happened also if you have same rows in 2 pickers!

推荐答案

在这里是这种情况:

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

a) the selectedValue should match the tag value, therefore in ForEach, it's better to use index not the id so that you can add tag for each items.

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

b) the ForEach structure is a complex one and usually to be reused for performance. So in order to force it refresh, id() modifier can be added to extra ForEach structures. There must be one ForEach without id which provides the real underlying data layer.

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

这篇关于swiftUi:在一个屏幕上有2个选择器-应用崩溃并显示“索引超出范围"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆