複数階層のビューにおいて一気にルートビューへ戻る方法【NavigationPathの活用】

この記事は約7分で読めます。

NavigationPathはSwiftUIで導入されたクラスで、ナビゲーションスタック内のパスを表します。
これにより、プログラマティックにナビゲーションスタックを管理することが可能になります。
NavigationPathは特にNavigationStackと組み合わせて使用され、複数のビュー間のナビゲーションをより細かく制御するために役立ちます。

複数階層のビューで一気にルートビューへ戻る方法

本ページでは複数階層で構成されたビューにおいてNavigationPathを活用して、一気にルートビューへ戻る画面遷移を作成してみます。

どのような動作?

完成すると以下のような画面遷移を作成できます。
『親ビュー → 子ビュー → 孫ビュー → 親ビュー』

サンプルコード

サンプルコードは以下のとおりです。

サンプルのプログラム構成

  • NavigationPathSmp:はじめに表示する親ビュー
  • SecondViewSmp:2つ目に画面遷移する子ビュー
  • ThirdViewSmp:3つ目に画面遷移する孫ビュー
  • FirstView:子ビューへ遷移する際にnavigationDestinationのパラメータである宛先に指定するためのenum
  • SecondView:孫ビューへ遷移する際にnavigationDestinationのパラメータである宛先に指定するためのenum

プログラム

ビューには、NavigationPathのスタック数が格納されており、”NavigationPath Count”として表示させています。画面遷移するたびにカウントが増えていくのがわかります。

親ビューのボタンを押すと、子ビューに画面遷移し、子ビューのボタンを押すと孫ビューに遷移します。最後に孫ビューでボタンを押すと、NavigationPathのスタックがクリアされルートビューに戻ります。

import SwiftUI

struct NavigationPathSmp: View {
    // NavigationPathのインスタンスを作成
    @State var path = NavigationPath()

    var body: some View {
        NavigationStack(path: $path) {
            Text("NavigationPath Count : \(path.count)")
            // ルートビュー
            Button("Go to Child View") {
                // プログラムによるナビゲーション
                path.append(FirstView.A)
            }
            .navigationDestination(for: FirstView.self) { id in
                // idに基づいて表示するビューを決定
                switch id {
                case .A: SecondViewSmp(path: $path)
                case .B: Text("Nothing")
                }
            }
            .navigationTitle("First View")
        }
    }
}

struct SecondViewSmp: View {
    @Binding var path: NavigationPath
    
    var body: some View {
        Text("NavigationPath Count : \(path.count)")
        Button("Go to Child View") {
            // プログラムによるナビゲーション
            path.append(SecondView.A)
        }
        .navigationDestination(for: SecondView.self) { id in
            // idに基づいて表示するビューを決定
            switch id {
            case .A: ThirdViewSmp(path: $path)
            case .B: Text("Nothing")
            }
        }
        .navigationTitle("Second View")
    }
}

struct ThirdViewSmp: View {
    @Binding var path: NavigationPath
    
    var body: some View {
        Text("NavigationPath Count : \(path.count)")
        Button("Back Root View") {
            path.removeLast(path.count)
        }
        .navigationTitle("Third View")
    }
}

// 宛先に指定するためのenum
enum FirstView:String,CaseIterable {
    case A
    case B
}
enum SecondView:String,CaseIterable {
    case A
    case B
}

サンプルコードのポイント

NavigationPathの使い方

画面遷移においてナビゲーションパス(pathプロパティ)をバインドして親ビューから孫ビューまで受け渡しをしています。
画面遷移する際は、pathに宛先を特定するためのFirstViewやSecondViewのenumの値を格納します。

そして、孫ビューにおいて“path.removeLast(path.count)”を使用してスタック数分のパスをクリアすることで親ビューに戻ります。
このようにNavigationPathの値を操作することで画面遷移をプログラムしています。

navigationDestinationにenumを使用する

navigationDestinationにはInt型やString型など既存の型を指定することも可能です。しかし、複数階層において同じ型をnavigationDestinationに指定してしまうと、意図した動作にならないことがあります。
これは、navigationDestinationの仕様がデータ型によって、宛先を判別しているためです。

navigationDestination(for:destination:) | Apple Developer Documentation
Associates a destination view with a presented data type for use within a navigation stack.

そのため、enumで新たな型を定義し、階層ごとに型を分けています。

NavigationPathを活用する特徴と利点

  • 動的なナビゲーションNavigationPathを使用すると、コードによるナビゲーションが可能になり、アプリケーションのフローを動的に変更できます。
  • 柔軟性:ナビゲーションスタックの操作がプログラムによって行われるため、複雑なナビゲーションロジックや条件に基づくナビゲーションが実現可能です。
  • 簡単なスタック管理:ナビゲーションスタックから特定のビューを削除したり、スタックを特定の状態にリセットしたりすることが容易になります。

まとめ

本記事では、NavigationPathの活用方法の一つである複数階層におけるルートビューへの戻り方を紹介しました。

NavigationPathを活用するともっと複雑な動作を簡単に実現できる活用方法がありそうです。他の動作についても試してみたらご紹介したいと思います。

タイトルとURLをコピーしました