Search code examples
iosswiftipadswiftuiswiftui-navigationsplitview

Programatic navigation on NavigationSplitView in SwiftUI


I have an app originally designed for iPad using NavigationSplitView. On a phone, I want it to automatically navigate to the detail view under certain circumstances. I have found the isActive property of NavigationLink, but this only works with NavigationStack, not split view. Is there a way to do this without converting everything to NavigationStack, or having to build separate views for phone and pad?

struct ScoringSplitView: View {
    @State var game: Game?
    @State var newGameViewModel: NewGameViewModel?

    var body: some View {
        NavigationSplitView {
            leftPanel
        } detail: {
            if let game = game {
                GameAlertContainerView(game: game)
            } else {
                GameScoringView(game: nil)
            }
        }
    }

    var leftPanel: some View {
        if let game = game {
            return AnyView(PlayerList(game: game))
        } else if let viewModel = newGameViewModel {
            return AnyView(NewGameView(viewModel: viewModel))
        } else {
            return AnyView(Text("placeholder")
        }
    }
struct PlayerList: View {
    @ObservedObject var game: Game

    var body: some View {
        VStack {
            TeamNamesView(game: game)
            BattingPlayerList(game: game)
        }
        .toolbar {
            if UIDevice.isIPhone { // from an extension
                ToolbarItem {
                    NavigationLink("Score") { // isActive doesn't work
                        GameAlertContainerView(game: game)
                    }
                }
            }

Right now the Score button takes the user to the scoring view, but I want it to go there automatically with a back button to the player list


Solution

  • I figured out how to do it with the navigationDestination view modifier and isPresented:

    @State var showScore = true
    // ...
            .navigationDestination(isPresented: $showScore) {
                GameAlertContainerView(game: game)
            }