Этот рвал мне волосы, надеюсь, кто-нибудь покажет мне, где я ошибаюсь.
Цель в том, что мне нужно иметь возможность управлять динамическим c списком элементы (то есть список может увеличиваться или уменьшаться), где свойства каждого элемента могут быть скорректированы (отредактированы), а элементы связаны с данным родителем.
В сокращенном коде ниже я назвал элемент Cell , который принадлежит строке. Строка может иметь много ячеек, и каждая ячейка имеет количество, которое может быть изменено пользователем. Это сокращенная версия моего кода, которая, я надеюсь, делает маркировку отношений немного более ясной, но, что особенно важно, она дает мне ту же ошибку, которая:
Если количество ячеек меньше исходного количества ( т.е. 3 или меньше в этом примере), тогда приложение вылетает с ошибкой «Индекс вне диапазона» всякий раз, когда представление закрывается. До этого момента ячейки могут быть добавлены или удалены без каких-либо проблем, и я не получаю эту ошибку при изменении количества элементов ячеек. Я просмотрел все SO и различные блоги и не могу найти никого, кто сталкивался с этой конкретной проблемой - кажется, что большинство сообщений Index вне диапазона происходит при фактическом изменении списка, моя ошибка возникает только после того, как список сокращается и затем отклонено.
Я приложил пример кода ниже - вы сможете вырезать / вставить и попробовать его.
PS. Я знаю, что calculateTotals () - это скетч; пожалуйста, не добавляйте буквы или знаки препинания к сумме - это просто для проверки правильности привязки:)
Ячейка
struct Cell: Identifiable {
var amount: String
var id = UUID()
init(_ amount: String = "0.00"){
self.amount = amount
}
}
Строка
class Row: ObservableObject {
@Published var cells: [Cell]
init(){
self.cells = [
Cell("10"),
Cell("15"),
Cell("20"),
Cell("25")]
}
}
ContentView
struct ContentView: View {
@State private var displayAmounts = false
var body: some View {
NavigationView {
Button(action: {
self.displayAmounts.toggle()
}) {
Text("View amounts")
}
}
.sheet(isPresented: self.$displayAmounts) {
CellSheet()
}
}
}
CellSheet
struct CellSheet: View {
@ObservedObject var row: Row = Row()
private func deleteCell(at offsets: IndexSet) {
self.row.cells.remove(atOffsets: offsets)
}
private func calculateTotals() -> String {
var total = Double("0.00")!
for cell in self.row.cells {
if( "" != cell.amount ) {
total += Double(cell.amount)!
}
}
return String("\(total)")
}
var body: some View {
VStack{
List {
ForEach(row.cells.indices, id: \.self){ i in
CellItem(amount: self.$row.cells[i].amount)
}.onDelete(perform: deleteCell)
}
Button(action: {
self.row.cells.append(Cell())
}) {
Text("Add new cell")
}
Text(calculateTotals())
}
}
}
CellItem - здесь некоторая странность: если я заключу TextField в HStack, тогда приложение сразу выйдет из строя при удалении ячейки - даже если общее количество ячеек больше исходного количества (4).
struct CellItem: View {
@Binding var amount: String
var body: some View {
// Uncomment HStack and deleting rows immediately causes index out of range.
// HStack {
TextField("Amount: ", text: $amount)
// }
}
}
Я действительно не понимаю, почему и как это происходит. Очевидно, что Swift пытается получить доступ к несуществующему индексу (если я удалю привязку и просто выведу значение, проблем не возникнет), но я не понимаю, почему это может вызвать проблемы при закрытии представления. Я предполагаю, что Swift кеширует некоторые вещи в памяти? Проблема с упаковкой HStack также необычна.
В любом случае, я относительно новичок в Swift, поэтому, возможно, я упускаю из виду что-то очевидное. Для дополнительного контекста я запускаю XCode 11.4.1 и нацелен на iOS 13.4.
Вы сможете перенести весь этот код прямо в новый проект, и он будет компилироваться. Любая помощь будет с благодарностью получена :)