【发布时间】:2022-06-13 20:39:58
【问题描述】:
请看下面的代码。按下按钮一次(或最多两次)几乎肯定会使应用程序崩溃。该应用程序显示一个包含两个部分的列表,每个部分有四个项目。当按下按钮时,它会在每个部分中插入一个新项目并更改部分顺序。
我刚刚向 Apple 提交了 FB9952691。但我想知道是否有人碰巧知道 1) UIKit 是否有同样的问题?我只是好奇(我最后一次使用 UIkit 是在两年前)。 2) 是否可以在 SwiftUI 中解决该问题?谢谢。
import SwiftUI
let groupNames = (1...2).map { "\($0)" }
let groupNumber = groupNames.count
let itemValues = (1...4)
let itemNumber = itemValues.count
struct Item: Identifiable {
var value: Int
var id = UUID()
}
struct Group: Identifiable {
var name: String
var items: [Item]
var id = UUID()
// insert a random item to the group
mutating func insertItem() {
let index = (0...itemNumber).randomElement()!
items.insert(Item(value: 100), at: index)
}
}
struct Data {
var groups: [Group]
// initial data: 2 sections, each having 4 items.
init() {
groups = groupNames.map { name in
let items = itemValues.map{ Item(value: $0) }
return Group(name: name, items: items)
}
}
// multiple changes: 1) reverse group order 2) insert a random item to each group
mutating func change() {
groups.reverse()
for index in groups.indices {
groups[index].insertItem()
}
}
}
struct ContentView: View {
@State var data = Data()
var body: some View {
VStack {
List {
ForEach(data.groups) { group in
Section {
ForEach(group.items) { item in
Text("\(group.name): \(item.value)")
}
}
header: {
Text("Section \(group.name)")
}
}
}
Button("Press to crash the app!") {
withAnimation {
data.change()
}
}
.padding()
}
}
}
更多信息:
- 错误信息:
由于未捕获的异常“NSInternalInconsistencyException”而终止应用,原因:“UITableView 内部不一致:在准备批量更新时遇到超出范围的全局行索引(oldRow=8,oldGlobalRowCount=8)”
- 问题不是由动画引起的。删除
withAnimation仍然有同样的问题。我认为该问题是由部分顺序更改引起的(尽管偶尔可以正常工作)。
更新:感谢@Yrb 指出insertItem() 中的一个超出索引的错误。该函数是示例代码中的设置实用程序,与change() 的问题无关。所以请忽略它。
【问题讨论】: