0

I have an issue with SwiftUI navigation. To show the issue I made a simple example of a list of cars and if the user clicks on it, it shows the car details:

struct ContentView: View {
    var cars = [Car(name: "A"), Car(name: "B"), Car(name: "C"), Car(name: "D")]
    
    var body: some View {
        NavigationView {
            LazyVStack(spacing: 10) {
               ForEach(cars, id: \.self) { car in
                   NavigationLink(destination: {
                       CarDetailsView(viewModel: CarDetailsViewModel(car: car))
                   },
                   label: {
                       CarRowView(car: car)
                   })
               }
           }
        }
    }
}

struct CarDetailsView: View {
    @StateObject var viewModel: CarDetailsViewModel
    @Environment(\.presentationMode) private var presentationMode
    
    var body: some View {
        Button("Back") {
            presentationMode.wrappedValue.dismiss()
        }
    }
}

class CarDetailsViewModel: ObservableObject {
    @Published var car: Car
    
    init(car: Car) {
        self.car = car
    }
}

struct Car: Hashable {
    var name: String
}

struct CarRowView: View {
    var car: Car
    
    var body: some View {
        Text(car.name)
    }
}

This works well when you select one car at the time. Unfortunatly with swiftUI I cannot disabled multi selection. If the user select multiple cars at the same time, and then go back to the car list sometime I get an error log:

SwiftUI encountered an issue when pushing aNavigationLink. Please file a bug.

At that moment, the car list is no longer responsive. It takes few attempt but it does eventually happen. I can only replicate this on iOS 15 so far. I also tried to do this without the viewModel and it still happen. Ideally I want to keep the NavigationLink inside the VStack because it makes the row dimming when the user selects it.

pierre23
  • 3,846
  • 1
  • 28
  • 28

1 Answers1

1

I can reproduce your issue, and I think this is a bug. However using the following NavigationLink setup with selection and tag seems to works for me.

struct ContentView: View {
    @State var cars = [Car(name: "A"), Car(name: "B"), Car(name: "C"), Car(name: "D")]
    @State private var showCar: UUID?

    var body: some View {
        NavigationView {
            LazyVStack(spacing: 30) {
                ForEach(cars) { car in
                    NavigationLink(
                         destination: CarDetailsView(car: car),
                         tag: car.id,
                         selection: $showCar,
                         label: { CarRowView(car: car) }
                     )
                }
            }
        }
    }
}

struct CarDetailsView: View {
    @Environment(\.dismiss) private var dismiss
    @State var car: Car

    var body: some View {
        Button("Back \(car.name)") {
            dismiss()
        }
    }
}

struct Car: Identifiable, Hashable {
    let id = UUID()
    var name: String
}

struct CarRowView: View {
    var car: Car
    
    var body: some View {
        Text(car.name)
    }
}