致命错误:索引超出范围:从数组中删除元素时文件 Swift/ContigouslyArrayBuffer.swift

Ano*_*ude 9 swiftui

我有一个表单来选择一些用户并为他们分配一个 int 值。

该模型:

class ReadingTime: Identifiable, Hashable {
    var id: Int
    @State var user: User
    @Published var value: Int

    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
    
    static func == (lhs: ReadingTime, rhs: ReadingTime) -> Bool {
        lhs.id == rhs.id
    }
    
    init(id: Int, user: User, value: Int) {
        self.id = id
        self._user = State(wrappedValue: user)
        self.value = value
    }
}
Run Code Online (Sandbox Code Playgroud)

风景:

@Binding var times: [ReadingTime]
@State var newUser: User?

func didSelect(_ user: User?) {
    if let user = user {
        readingTime.append(ReadingTime(id: readingTime.nextMaxId,
                                       user: user,
                                       value: 0))
    }
}

// In the body:
VStack(alignment: .leading, spacing: 0) {
    HStack {
        Picker("Select a user", selection: $newUser.onChange(didSelect)) {
                    ForEach(users) {
                        Text($0.name).tag(Optional($0))
                    }
                }
                .id(users)
            }
            VStack(spacing: 8) {
                ForEach(0..<times.count, id: \.self) { i in
                    HStack(spacing: 0) {                            
                        Text(times[i].user.name)
                        TextField("ms", value: $times[i].value, formatter: NumberFormatter())
                        Button(action: {
                            NSApp.keyWindow?.makeFirstResponder(nil)
                            if let index = times.firstIndex(where: { $0 == times[i] }) {
                                times.remove(at: index)
                            }
                            newUser = nil
                        }, label: {
                            Text("REMOVE")
                        })
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它看起来像这样:

在此输入图像描述

但是,当删除列表中的条目时,我收到此错误:

致命错误:索引超出范围:文件 Swift/ContigeousArrayBuffer.swift

这里发生了什么?

vad*_*ian 7

在枚举时修改数组的项数是一个邪恶的陷阱。

0..<times.count创建临时静态范围。

如果删除数组中的第一项,索引 1 将变为 0,索引 2 将变为 1,依此类推。

不幸的是,不再有索引,当循环到达最后一个索引时,times.count-1您会崩溃。Index out of range

如果枚举反转的数组,则可以避免崩溃。