How to navigate from one page set to another in WatchKit
Navigating between Storyboard layouts when supporting watchOS 6

by Lou Franco

In the last article we learned about page-based navigation on an Apple Watch. It's trivial if you are targeting watchOS 7, but in watchOS 6, WatchKit didn't use SwiftUI for the entry-point of the app and you still needed Storyboards to define pages.

If you are targeting watchOS 6, and you have several possible root views, then you define each in a Storyboard and you need to navigate between them outside of SwiftUI.

Example of a watch app with multiple root views

The Workout app on your watch is an example of an app that needs this kind of UI. In fact, pretty much any workout app would probably do it this way, and my own app, Sprint-o-Mat uses it as well.

When you start a workout app, you usually have a UI that shows you all of the possible workouts you could do and interacting with them lets you set them up.

In Sprint-o-Mat, it looks like this when you are setting up a workout (this uses a List and NavigationLinks as described in this article)

Screens to set up a sprint

But, then when you start a workout, the UI changes to a page-based navigation structure that only has screens that let you interact with the workout itself.

Screens shown during a workout

And, when the workout is done, it navigates back to the initial root view.

How to change the root pages

In the last article, I showed how you create HostingController classes for each page and how to connect them to the Storyboard.

In Sprint-o-Mat, the three pages that are shown during a workout are called WorkoutActionHostingController, WorkoutHostingController, and NowPlaying. When you start a workout, I need to call WKInterfaceController.reloadRootPageControllers() to reset the root to these pages. Here is the full call

    withNames: ["WorkoutActionHostingController", "WorkoutHostingController", "NowPlaying"],
    contexts: [pageContext, pageContext],
    orientation: .horizontal,
    pageIndex: 1)

This says to load the three pages and provide the first two with pageContext objects. The pages are horizontally laid out (so that you navigate with left and right swipes), and the workout page (at index 1) is the initial screen.

In my app, pageContext holds all of the information needed to actually do the workout. The media player screen doesn't need it.

Navigating back is similar:

    withNames: ["MainHostingController"],
    contexts: [context],
    orientation: .horizontal,
    pageIndex: 0)

When I actually start a workout, there's a countdown animation to give you three seconds to get ready to run. I'll show you how to do that in the next article.

Subscribe to be notified of the next WatchKit article

Make sure to sign up to my newsletter to get notified when a new article is published.

Contact me if you are working on a Watch app and need help.

Never miss an article

Get more articles like this in your inbox.