NavigationStack and binding to a selection

42 views Asked by At

I'm developing a watch app similar to Apple's demo workout app, but as of watchOS9 NavigationView has moved to NavigationStack.

In the demo, a list of workouts are presented; when a workout is selected the SessionPagingView() is presented with the selected workout.

List(workoutTypes) { workoutType in
            NavigationLink(workoutType.name, destination: SessionPagingView(),
                           tag: workoutType, selection: $workoutManager.selectedWorkout)
                .padding(EdgeInsets(top: 15, leading: 5, bottom: 15, trailing: 5))
        }

However under WatchOS9+ this pattern is only available under NavigationSplitView() which presents the detail view first.

Is there anyway to replicate the original under NavigationStack?

link to Apple's demo code: https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/build_a_workout_app_for_apple_watch

1

There are 1 answers

1
chuanpham On

You can try to modify your code like this:

    @EnvironmentObject var workoutManager: WorkoutManager
    @State var presentedWorkout: [HKWorkoutActivityType] = []
    var workoutTypes: [HKWorkoutActivityType] = [.cycling, .running, .walking]
    
    var body: some View {
        NavigationStack(path: $presentedWorkout) {
            List(workoutTypes) { workoutType in
                NavigationLink(
                    workoutType.name,
                    value: workoutType
                )
                .navigationDestination(for: HKWorkoutActivityType.self) { workoutType in
                    SessionPagingView()
                }
                .onChange(of: presentedWorkout) { _ in
                    guard let workout = presentedWorkout.last else { return }
                    workoutManager.selectedWorkout = workout
                }
            }
            .listStyle(.elliptical)
            .navigationBarTitle("Workouts")
            .onAppear {
                workoutManager.requestAuthorization()
            }
        }
    }

When user taps on the list's item, you can use onChange(of) to catch the workout, and set this value to Workoutmanager.selectedWorkout.