'ForEach is retrieving wrong value in SwiftUI LazyVGrid

I am working on a SwiftUI LazyVGrid with a ForEach loop. I wanted to add buttons to each item in the LazyVGrid, and then process either an Edit, View, or Delete based on user selection. The Delete Buttonappears to work OK, but the NavigationLink’s for Edit and View seem to return a random object in the ForEach loop.

var body: some View {
        GeometryReader { geo in
            VStack {
                ScrollView {
                    LazyVGrid(columns: gridLayout, alignment: .center, spacing: 1) {
                        ForEach(events, id: \.self) { event in
                            HStack {
                                VStack {
                                    ZStack {
                                        Spacer()
                                        Image(uiImage: (event.cardFrontImage ?? blankCardFront)!)
                                        HStack {
                                            VStack {
                                                Spacer()
                                                Text("\(event.event ?? "")")
                                            }
                                        }
                                        VStack {
                                            HStack {
                                                Spacer()
                                                NavigationLink(destination: EditAnEvent(event: event, recipient: recipient), isActive: $isEditActive, label: {
                                                    Image(systemName: "square.and.pencil")
                                                })
                                                NavigationLink(destination: CardView(cardImage: (event.cardFrontImage ?? blankCardFront)!, event: event.event ?? "Unknown Event", eventDate: event.eventDate! as Date), isActive: $isCardActive, label: {
                                                    Image(systemName: "doc.text.image")
                                                })
                                                Button(action: {
                                                    areYouSure.toggle()
                                                }, label: {
                                                    Image(systemName: "trash")
                                                })
                                                .confirmationDialog("Are you Sure", isPresented: $areYouSure, titleVisibility: .visible) {
                                                    Button("Yes") {
                                                        withAnimation {
                                                            print("Deleting Event \(String(describing: event.event))")
                                                            deleteEvent(event: event)
                                                        }
                                                    }
                                                    Button("No") {
                                                        withAnimation {
                                                            print("Cancelled delete of \(String(describing: event.event))")
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            .frame(height: geo.size.width * 0.3)
                            .background(Color(.systemGray5))
                            .overlay(
                                RoundedRectangle(cornerRadius: 20)
                                    .stroke(Color.white, lineWidth: 20)
                            )
                        }
                    }
                }
            }
        }
        .accentColor(.green)

I’ve removed as much formatting to reduce the number of lines, and demonstrate the problem.



Solution 1:[1]

Breaking the Views up should help fix it. E.g. put the delete button and confirmation in its own View.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1