#swiftui
Вопрос:
Я хотел бы создать представление, в которое я могу передать массив, и заставить представление редактировать массив. Следующий код является упрощенным примером:
struct Item: Identifiable {
var name: String
var id = UUID()
}
struct EditItems: View {
@Binding var item_list: [Item]
var body: some View {
List {
ForEach(item_list.indices) { idx in
Text(item_list[idx].name)
}
.onDelete(perform: deleteItem)
}
.toolbar {
ToolbarItem(placement: .principal) {
EditButton()
}
}
}
func deleteItem(at offsets: IndexSet) {
item_list.remove(atOffsets: offsets)
}
}
Это компилируется и запускается изначально. Я могу нажать «Редактировать» и удалить элемент списка. После удаления элемента списка, когда я нажимаю «Готово», я получаю «Фатальная ошибка: индекс вне диапазона». Отладчик сообщает мне, что в моем списке 7 элементов, но строка Text(item_list[idx].name)
пытается выполнить с idx = 7
помощью .
Таким образом, похоже, что после удаления элемента ForEach
он все еще работает со старыми индексами вместо новых более коротких индексов. Это потому item_list
, что это не @State
так ? Когда я попытался сделать @State
и @Binding
то, и другое, и получил кучу ошибок.
Как мне это исправить?
Ответ №1:
Инициализатор для ForEach
этого принимает диапазон, который может использоваться только для постоянных данных.
Из документов Apple:
Экземпляр считывает только начальное значение предоставленных данных, и ему не нужно идентифицировать представления в обновлениях.
Используйте один из других ForEach
инициализаторов, например:
ForEach(item_list.enumerated(), id: .self) { idx, element in
Комментарии:
1. Ну, я буду, я никогда не замечал, что некоторые из них постоянны, а некоторые нет. Спасибо!
Ответ №2:
Вы использовали конструктор, из ForEach
которого создается постоянный контейнер, используйте другой, с явными идентификаторами, например
List {
ForEach(item_list.indices, id: .self) { idx in // << here !!
Text(item_list[idx].name)
}