出现“致命错误:索引超出范围”:在swiftui的列表项中显示索引

问题描述 投票:0回答:3

已更新:错误:类型'_'没有成员'1',为什么?关键路径表达问题?

代码版本4:

struct Timestamp: Identifiable, Hashable {
    var id: ID
    var name: String = ""
    var timeAt: Double = 0
    var marked: Bool = false
}

var timestamps: [Timestamp] { return ... }
var body: some View {
...
            List {
                ForEach(Array(zip(0..., timestamps)), id: \.1.id) { index, timestamp in // error: Type '_' has no member '1'
                    if !self.showMarkedOnly || timestamp.marked {
                        self.timestampItemView(timestamp, withIndex: index)
                    }
                }
            }
...
}

==========

已更新:我发现了代码版本2的问题,我必须提供ForEach的ID。并更新了代码版本2。

我发现了一种显示索引的优美方法,它避免了self.list [index]。但是我发现某些复杂代码中出现了错误“类型'_'没有成员'1'”。

代码版本3:

var body: some View {
        List {
            ForEach(Array(zip(0..., list)), id: \.1.id) { index, name in // a error occurs in some complex code: "Type '_' has no member '1'"
                HStack {
                    Text("\(index)")
                    Spacer()
                    Text("\(name.name)")
                }
                .background(Color.gray.opacity(0.001))
                .onTapGesture {
                    self.list.remove(at: index)
                }
            }
        }
    }

我显示一个列表,然后删除我点击的项目。它是代码版本1,工作正常。当我使用索引(代码版本2)将索引添加到列表项时,点击后出现“致命错误:索引超出范围”。

代码版本1:

struct Name: Identifiable, Hashable {
    var id: String = UUID().uuidString
    var name: String
    init(_ name: String) { self.name = name }
}

struct TestView: View {
    @State private var list: [Name] = [Name("test1"), Name("test2"), Name("test3"), Name("test4"), Name("test5"), Name("test6"), Name("test7"), Name("test8")]

    var body: some View {
        List {
            ForEach(list) { name in
                HStack {
                    Text("\(0)")
                    Spacer()
                    Text("\(name.name)")
                }
                .background(Color.gray.opacity(0.001))
                .onTapGesture {
                    self.list = self.list.filter { $0 != name }
                }
            }
        }
    }
}

代码版本2:

struct TestView: View {
    @State private var list: [Name] = [Name("test1"), Name("test2"), Name("test3"), Name("test4"), Name("test5"), Name("test6"), Name("test7"), Name("test8")]

    var body: some View {
        List {
            //ForEach(list.indices) { index in
            ForEach(list.indices, id: \.self) { index in
                HStack {
                    Text("\(index)")
                    Spacer()
                    Text("\(self.list[index].name)")
                }
                .background(Color.gray.opacity(0.001))
                .onTapGesture {
                    self.list.remove(at: index)
                }
            }
        }
    }
}
list swiftui indices
3个回答
1
投票

这是因为indices不是您的状态,而是数组。因此,您更新了数组,但是@State实际上不够聪明,无法更新其包装的值的计算或下游属性。如果需要索引,请在ForEach

中使标识符来源
ForEach(0..<list.count, id: \.self) {
    // the rest should be ok here
}

1
投票

@ State是属性包装器,它将强制对其定义的视图重新计算其主体。

根据您的情况,如果您删除索引处的项目,则>>

HStack {
    Text("\(index)")
    Spacer()
    Text("\(self.list[index].name)")
}
.background(Color.gray.opacity(0.001))
.onTapGesture {
     self.list.remove(at: index)
 }

HStack中的文本

Text("\(self.list[index].name)")

崩溃,仅因为list [index]不再存在。

使用中

ForEach(list.indices, id:\.self) { index in ... }

代替

ForEach(list.indices) { index in ... }

将强制SwiftUI重新创建TestView(请参阅ForEach构造函数中的id:\。self)

SwiftUI将使用包装在@State属性包装器中的属性的新值来制作TestView的新副本。


0
投票

这是因为SwiftUI根据所提供的原始数据重新加载其内容。您可以通过修改

© www.soinside.com 2019 - 2024. All rights reserved.