5.8 C
New York
Monday, December 9, 2024

ios – Getting ‘Deadly error index out of vary’ in two layer Lazy Stack with utilizing ForLoop SwiftUI


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+)

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles