首页 > 解决方案 > 绑定值源已删除

问题描述

出于某种原因,在使用状态(带有数组)并与其值之一绑定时,我得到一个索引超出范围错误。一般来说,向数组添加更多值是没有问题的。但是,当您尝试删除一个值时,您会得到一个索引超出范围的错误。

这是我在自己的项目中遇到的问题的简化版本。

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

标签: swiftbindingswiftui

解决方案


在这种情况下有两个原因:恒定的 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()
            }
        }
        }
    }
}

推荐阅读