Home > Software engineering >  Alert is taking wrong values inside LazyVGrid SwiftUI
Alert is taking wrong values inside LazyVGrid SwiftUI

Time:02-10

Alert should remove objects from a model, but when Alert is apearing, values are not the same as a value inside tap and longPress Gesture. Any idea why?

LazyVGrid(columns: columns, spacing: 5) {
            ForEach(model.robotsRepository.robots) { robot in
                RobotView(model: RobotView.Model(robotsRepository: model.robotsRepository, robot: robot)).environmentObject(team)
                    .contentShape(Rectangle())
                    .alert(isPresented: $showAlert) {
                        //When Alert is apearing, "robot" value are not the same as a value inside tap and longPress Gesture
                        Alert(
                            title: Text("Remove Card"),
                            message: Text("Are you sure you want to remove this card?"),
                            primaryButton: .destructive(Text("Remove")) {
                                withAnimation {
                                    model.remove(robot: robot)
                                }
                            },
                            secondaryButton: .cancel() {
                                withAnimation {
                                    deleting = false
                                }
                            }
                        )
                    }
                    .onTapGesture {
                        addRobot(robot: robot, at: selectedIndex)
                    }
                    .onLongPressGesture {
                        withAnimation {
                            showAlert = true
                            deleting = true
                        }
                    }
            }
        }

CodePudding user response:

you could try moving the .alert(isPresented: $showAlert) {...} out of the ForEach, and probably out of the LazyVGrid as well. Something like this, for example (untested):

@State var selectedRobot = Robot.default  // <--- here adjust accordingly

LazyVGrid(columns: columns, spacing: 5) {
            ForEach(model.robotsRepository.robots) { robot in
                RobotView(model: RobotView.Model(robotsRepository: model.robotsRepository, robot: robot)).environmentObject(team)
                    .contentShape(Rectangle())
                    .onTapGesture {
                        addRobot(robot: robot, at: selectedIndex)
                    }
                    .onLongPressGesture {
                        withAnimation {
                            selectedRobot = robot  // <-- here
                            showAlert = true
                            deleting = true
                        }
                    }
            }
        }
        .alert(isPresented: $showAlert) {
            Alert(
                title: Text("Remove Card"),
                message: Text("Are you sure you want to remove this card?"),
                primaryButton: .destructive(Text("Remove")) {
                    withAnimation {
                        model.remove(robot: selectedRobot) // <-- here
                    }
                },
                secondaryButton: .cancel() {
                    withAnimation {
                        deleting = false
                    }
                }
            )
        }
     

EDIT-1: Note that alert(isPresented:content:) and alert(item:content:) are deprecated (iOS 13.0–15.4 ).

If you are using (ios15 ) you can use the following approach (as per the Apple example: https://developer.apple.com/documentation/swiftui/view/alert(_:ispresented:presenting:actions:message:)-8584l)

// for demonstration
struct Robot: Identifiable {
    let id = UUID()
    let name: String = "no name"
}

.....

@State var selectedRobot: Robot?  // <--- here

 .....

        LazyVGrid(columns: columns, spacing: 5) {
            ForEach(model.robotsRepository.robots) { robot in
                RobotView(model: RobotView.Model(robotsRepository: model.robotsRepository, robot: robot)).environmentObject(team)
                    .contentShape(Rectangle())
                    .onTapGesture {
                        addRobot(robot: robot, at: selectedIndex)
                    }
                    .onLongPressGesture {
                        withAnimation {
                            selectedRobot = robot  // <-- here
                            showAlert = true
                            deleting = true
                        }
                    }
            }
        }
        .alert("Remove Card", isPresented: $showAlert, presenting: selectedRobot) { robot in
            Button(role: .destructive) {
                withAnimation {
                    model.remove(robot: robot) 
                }
            } label: { Text("Remove") }
            
            Button(role: .cancel) {
                withAnimation {
                    deleting = false
                }
            } label: { Text("Cancel") }
            
        } message: { _ in
            Text("Are you sure you want to remove this card?")
        }
     
  • Related