由于某种原因,在使用状态(带有数组)并绑定其值之一时,出现索引超出范围的错误。通常,向数组添加更多值没有问题。但是,当您尝试删除一个值时,您将获得索引超出范围的错误。
这是我自己的项目中遇到的问题的简化版本。
尝试下面的SwiftUI示例。只需按住一个圈子即可尝试删除一个圈子!删除时会出现Swift错误:Fatal error: Index out of range: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.2.25.8/swift/stdlib/public/core/ContiguousArrayBuffer.swift, line 444
我相信该错误来自以下事实:要删除的值受CustomView
的value
之一约束。删除后,视图不再有权访问该值,从而触发越界错误。
import SwiftUI
struct Test: View {
@State var values: [Int] = [0, 1, 1, 1]
var totalBalls: Int {
return values.count
}
var body: some View {
HStack {
Text("\(totalBalls)")
VStack {
ForEach(0..<values.count, id: \.self) { i in
CustomView(value: self.$values[i])
}
.onLongPressGesture {
self.values.removeLast() //this line causes an error!
}
}
}
}
}
struct CustomView: View {
@Binding var value: Int
var body: some View {
ZStack {
Circle()
Text("\(value)").foregroundColor(Color.orange)
}.onTapGesture {
self.value+=1
}
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
Test()
}
}
在这种情况下,有两个原因:ForEach保持不变,并通过直接出价刷新竞速。
这里是解决崩溃并按预期工作的解决方案。经过Xcode 11.4 / iOS 13.4的测试。
struct TestDeleteLast: View {
@State var values: [Int] = [0, 1, 1, 1]
var totalBalls: Int {
return values.count
}
var body: some View {
HStack {
Text("\(totalBalls)")
VStack {
// use index as id in ForEach
ForEach(Array(values.enumerated()), id: \.0.self) { i, _ in
CustomView(value: Binding( // << use proxy binding !!
get: { self.values[i] },
set: { self.values[i] = $0 }))
}
.onLongPressGesture {
self.values.removeLast()
}
}
}
}
}