list - SwiftUI:无法删除列表中的行
问题描述
我在 Xcode 中有一个小的 swiftUI 程序,它可以让我在一个列表中创建和删除用户,并使用步进器来计算用户的点数。
除非删除用户,否则一切正常(添加用户、重命名用户、步进计数)。
它抛出一个错误:
致命错误:索引超出范围:文件 /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.2.25.8/swift/stdlib/public/core/ContiguousArrayBuffer.swift,第 444 行 2020-05-23 12 :06:22.854920 + 0200计数器[21328:1125981]致命错误:索引超出范围:文件/Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.2.25.8/swift/stdlib/public/core/ ContiguousArrayBuffer.swift,第 444 行
这是代码:
import SwiftUI
struct ContentView : View {
@State var isEditing = false
@State var stepperWerte = [3, 5, 7, 9]
@State var editText = ["Player 1", "Player 2", "Player 3", "Player 4"]
var startName = "new Player"
var startLeben = 5
var body: some View {
NavigationView {
List() {
ForEach(0..<editText.count, id: \.self) {
spieler in HStack {
if self.editText.indices.contains(spieler) {
Stepper(value: self.$stepperWerte[spieler], in: -1...10, step: 1, label: {
TextField("", text: self.$editText[spieler], onEditingChanged: {_ in }, onCommit: {self.saveText(id: spieler, Text: self.editText[spieler])} )
.layoutPriority(1)
.fixedSize(horizontal: true, vertical: false)
Text("\(self.stepperWerte[spieler]) - \(spieler) - \(self.editText.count)")})
}
}
}
.onDelete(perform: spielerLoeschen)
.frame(width: nil, height: nil, alignment: .trailing)
}
.navigationBarTitle(Text("Nav_Title"))
.navigationBarItems(leading: Button(action: { self.isEditing.toggle() }) { Text(isEditing ? "Done" : "Edit").frame(width: 85, height: 40, alignment: .leading) },
trailing: Button(action: spielerHinzufuegen, label: { Image(systemName: "plus") }) )
.environment(\.editMode, .constant(self.isEditing ? EditMode.active : EditMode.inactive)).animation(Animation.spring())
}
}
func spielerLoeschen(at offsets: IndexSet) {
stepperWerte.remove(atOffsets: offsets)
editText.remove(atOffsets: offsets)
}
func spielerHinzufuegen() {
stepperWerte.append(startLeben)
editText.append(startName)
}
func saveText(id: Int, Text: String) {
editText[id] = Text
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
(忽略HStack后面的“if”,它没有实际效果,最后文本中的那些额外打印显示索引和总数)
如果我转储数组(stepperWerte 和 editText),它们会以正确的方式删除 -> 选择删除的播放器将从两个数组中正确删除。
如果我改变
TextField("", text: self.$editText[spieler]
至
TextField("", text: self.$editText[0]
它可以工作(除非它自然地显示所有行中的第一个玩家,并且在删除所有玩家(=行)后我得到了同样的错误)
任何帮助都会很棒-谢谢!
解决方案
根据@Asperi,我已将代码更改为以下内容:导入 SwiftUI
struct BetterTextField : View {
var container: Binding<[String]>
var index: Int
@State var text: String
var body: some View {
TextField("", text: self.$text, onCommit: {
self.container.wrappedValue[self.index] = self.text
})
.layoutPriority(1)
.fixedSize(horizontal: true, vertical: false)
}
}
struct ContentView : View {
@State var isEditing = false
@State var stepperWerte = [3, 5, 7, 9]
@State var editText = ["Player 1", "Player 2", "Player 3", "Player 4"]
var startName = "new Player"
var startLeben = 5
var body: some View {
NavigationView {
List() {
ForEach(0..<editText.count, id: \.self) {
spieler in HStack {
if self.editText.indices.contains(spieler) {
Stepper(value: self.$stepperWerte[spieler], in: -1...10, step: 1, label: {
BetterTextField(container: self.$editText, index: self.editText.firstIndex(of: self.editText[spieler])!, text: self.editText[spieler])
Text("\(self.stepperWerte[spieler]) - \(spieler) - \(self.editText.count)")})
}
}
}
.onDelete(perform: spielerLoeschen)
.frame(width: nil, height: nil, alignment: .trailing)
}
.navigationBarTitle(Text("Nav_Title"))
.navigationBarItems(leading: Button(action: { self.isEditing.toggle() }) { Text(isEditing ? "Done" : "Edit").frame(width: 85, height: 40, alignment: .leading) },
trailing: Button(action: spielerHinzufuegen, label: { Image(systemName: "plus") }) )
.environment(\.editMode, .constant(self.isEditing ? EditMode.active : EditMode.inactive)).animation(Animation.spring())
}
}
func spielerLoeschen(at offsets: IndexSet) {
stepperWerte.remove(atOffsets: offsets)
editText.remove(atOffsets: offsets)
}
func spielerHinzufuegen() {
stepperWerte.append(startLeben)
editText.append(startName)
}
func saveText(id: Int, Text: String) {
editText[id] = Text
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
...它的工作原理 - 谢谢!
但是:这是 SwiftUI 中的错误还是故意的?
推荐阅读
- python - python,我想在for循环中使用函数
- python - 来自 2 列数据的图表
- python - 在python中使用逻辑回归的一对一和一对一多类分类
- javascript - 为什么这个代码打印错误的素数?
- jenkins - Jenkins groovy 脚本参数从另一个工作中获取
- python - 一次获取 Tensorflow 中多个元素的索引
- android - 如何重现错误?
- javascript - 如何在 Docker 上部署的 React JS 应用程序中隐藏 API 密钥和机密
- html - 为单选输入实现 CSS 默认浏览器
- c++ - ClipperLib 中 ptSubject 和 ptClip 的区别