I’ve an array of components that comprises a nested array of different components inside.
When deleting a row of an array, typically a crash happens with the message ‘Swift/ContiguousArrayBuffer.swift:600: Deadly error: Index out of vary’, not pointing at concrete line of code.
This is my minimal reproducible code:
// View parts
struct ContentView: View {
@StateObject var viewModel: ViewModel = .init()
var physique: some View {
ScrollView {
LazyVStack {
ForEach($viewModel.assetsRows, id: .self) { assetsRow in
VStack {
Button(motion: {
viewModel.deleteSelected(assetsIn: assetsRow.wrappedValue)
}, label: {
HStack {
Picture(systemName: "trash")
Textual content("Delete row")
}
})
RowView(assetsRow: assetsRow)
}
}
}
}
}
}
struct RowView: View {
@Binding var assetsRow: AssetsRowModel
var physique: some View {
ScrollView(.horizontal) {
LazyHStack {
ForEach($assetsRow.objects, id: .self) { merchandise in
GridItemView(
assetItem: merchandise,
picture: .init(systemName: "picture.fill")
)
}
}
}
}
}
struct GridItemView: View {
@Binding var assetItem: AssetItem
@State var picture: Picture?
var physique: some View {
Group {
if let picture = picture {
picture
} else {
ProgressView()
}
}
.body(width: 200, peak: 120)
.overlay(alignment: .bottomTrailing) {
Toggle(isOn: $assetItem.isSelected) {
Textual content("checkmark")
}
.padding(4)
}
.onAppear {
// fetch picture logic
}
}
}
@MainActor closing class ViewModel: ObservableObject {
@Revealed var assetsRows: [AssetsRowModel] = {
var array: [AssetsRowModel] = []
for i in 0..<30 {
array.append(.init(objects: [.init(), .init(), .init()]))
}
return array
}()
// eradicating objects causes crash (not 100% occasions)
func deleteSelected(assetsIn row: AssetsRowModel) {
withAnimation {
assetsRows.removeAll { aspect in
aspect.id == row.id
}
}
}
// different fetching logic
}
// Fashions
struct AssetsRowModel: Identifiable, Equatable, Hashable {
var id = UUID()
var objects: [AssetItem]
}
struct AssetItem: Identifiable, Hashable {
var id = UUID()
var isSelected = false
}
extension AssetItem: Equatable {
static func ==(lhs: AssetItem, rhs: AssetItem) -> Bool {
(lhs.id == rhs.id)
}
}
Tried to alter @Binding
to @State
in RowView
, it is stop the crash, however isSelected
does not working correctly, as a result of it is not ‘binding’ with viewModel’s worth.
I suppose that is an inner SwiftUI bug. (Xcode 15.4, iOS 17+)