システム開発<基本編>SwiftUIでNavigationStackを利用したナビゲーション画面遷移

Swift

前回は、SwiftUIで、Slider を利用して、色(HSB)をスライダ調整が出来る

アプリケーションを開発する記事を紹介しました。

 

 

今回は、SwiftUIで、NavigationStack を利用したナビゲーション画面遷移を行う

アプリケーションを紹介しようと思います。

SwiftUIでNavigationStackを利用したナビゲーション画面遷移

 

 

習得内容

今回、SwiftUIで NavigationStack を利用した画面遷移を行うアプリケーションを

作成する事で、下記の内容を習得する事が出来ます。

  • NavigationView:iOS15までナビゲーション画面遷移を実現していましたが、iOS16以降は非推奨になり、代わりに NavigationStack と NavigationSplitView が公開されて、ナビゲーション画面遷移を実現します。
  • NavigationStack:iOS16以降で、階層化(ディープリンク)したナビゲーション画面遷移を実現します。
  • NavigationSplitView:iOS16以降で、セクション分割をしたナビゲーション画面遷移を実現します。
  • NavigationLink:画面遷移のリンクを定義します。
  • .navigationDestination:遷移先のViewを指定する事で、画面遷移が実現します。

 

動作環境

今回も、アプリが動作する環境は下記になります。

  • mac OS:Sequoia 15.6.1
  • iOS:26.0
  • Xcode:26.0.1
  • Swift:6.2.1

 

 

NavigationStack

SwiftUIで NavigationStack を利用した画面遷移を行うアプリケーションを作成する前に

NavigationStack について、少し確認しておきます。

 

モーダル遷移とナビゲーション遷移

SwiftUIや UIKit で行う画面遷移の方法は、大きく分けて下記の2パターンあります。

  1. モーダル遷移:下から上に覆い被さるように遷移
  2. ナビゲーション遷移:左から右へ流れるようなアニメーションで遷移

 

モーダル遷移は、既に ContentView(メインメニュー:親画面) で実装していたので、

御理解を頂いていると思いますが、画面遷移の際に .fullScreenCover()  や .sheet() 

を利用する事で、QRCodeView(子画面)や ColorSliderHSBView(子画面)が

ContentView(親画面) に下から上に覆い被さる状況は確認済みです。

 

NavigationStack とは

では、ナビゲーション遷移はと言うと、iOS15まで、NavigationView を利用して

ナビゲーション遷移を実現していました。

しかし、コードによる画面遷移を実装していると、画面が増加していったり、

階層が深くなり(ディープリンク)、複雑化していきました。

iOS16以降では、NavigationViewは非推奨になり、その代わりに NavigationStack と

NavigationSplitView が公開されました。

NavigationStack は、NavigationViewを踏襲して、左から右へ流れるような画面遷移を

実現したり、階層化(ディープリンク)した画面遷移を実現します。

 

NavigationStack には、下記の3種類の画面遷移が用意されています。

  1. 直接遷移:リンクやボタンを押すことで、直接、画面遷移を実現します。(NavigationStack+NavigationLink)
  2. 遷移コントロール:リンクやボタンを押すことで、押したリンクの結果を受けて、画面遷移を一箇所でコントロールします。(NavigationStack+NavigationLink+navigationDestination)
  3. 配列コントロール:画面の遷移状況を管理する配列(path)を用意し、配列操作の結果を受けて、画面遷移を一箇所でコントロールします。(NavigationStack(path: $path)+navigationDestination)

今回の記事では、上記から、2:遷移コントロールを実現します。

 

NavigationStack による、3種類の画面遷移の詳細は、下記を参考にしています。

 

 

 

NavigationSplitView とは

NavigationSplitView は、iPadなどの大画面のデバイスで使用される事が多く、

2列(カラム)や3列(カラム)のレイアウトにセクション分割した画面遷移を実現します。

NavigationSplitView については、別の記事で紹介します。

 

NavigationStackを利用した画面遷移

では、NavigationStack を利用したナビゲーション画面遷移を行うアプリケーション

を作成していきます。

 

Xcode の上部タブメニューより、File → New → File from Template を選択します。

 

SwiftUI View を選択します。

 

名称は、NavigationListVeiw を入力してみます。

 

Create ボタンを押して、NavigationListVeiw.swift  を作成します。

 

ContentView:メインメニュー(ランチャー)

前回の記事で作成したメインメニュー(ランチャー):ContentView を確認します。

 


import SwiftUI

struct ContentView: View {

    @State var isPopupView_1 = false
    @State var isPopupView_2 = false
    @State var isPopupView_3 = false
    @State var isPopupView_4 = false

    var body: some View {
        
        VStack{
            Button {
                self.isPopupView_1.toggle()
            } label: {
                Text("QRCodeView")
                    .font(.title2)
            }
            .fullScreenCover(isPresented: $isPopupView_1, content: {
                QRCodeView(isPopupView_1: $isPopupView_1)
            })
            .padding()

            Button {
                self.isPopupView_2.toggle()
            } label: {
                Text("ColorPickerView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_2, content: {
                ColorPickerView(isPopupView_2: $isPopupView_2)
            })
            .padding()

            Button {
                self.isPopupView_3.toggle()
            } label: {
                Text("ColorSliderRGBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_3, content: {
                ColorSliderRGBView(isPopupView_3: $isPopupView_3)
            })
            .padding()

            Button {
                self.isPopupView_4.toggle()
                
            } label: {
                Text("ColorSliderHSBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_4, content: {
                ColorSliderHSBView(isPopupView_4: $isPopupView_4)
            })
            .padding()
        }
    }
}

#Preview {
    ContentView()
}

 

メインメニュー(ランチャー)は、以下の内容です。

  • QRCodeView
  • ColorPickerView
  • ColorSliderRGBView
  • ColorSliderHSBView

 

モーダル表示:sheet()

先程、作成した NavigationListVeiw を ContentView のメニューに追加します。

 


import SwiftUI

struct ContentView: View {

    @State var isPopupView_1 = false
    @State var isPopupView_2 = false
    @State var isPopupView_3 = false
    @State var isPopupView_4 = false
    @State var isPopupView_5 = false

    var body: some View {
        
        VStack{
            Button {
                self.isPopupView_1.toggle()
            } label: {
                Text("QRCodeView")
                    .font(.title2)
            }
            .fullScreenCover(isPresented: $isPopupView_1, content: {
                QRCodeView(isPopupView_1: $isPopupView_1)
            })
            .padding()

            Button {
                self.isPopupView_2.toggle()
            } label: {
                Text("ColorPickerView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_2, content: {
                ColorPickerView(isPopupView_2: $isPopupView_2)
            })
            .padding()

            Button {
                self.isPopupView_3.toggle()
            } label: {
                Text("ColorSliderRGBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_3, content: {
                ColorSliderRGBView(isPopupView_3: $isPopupView_3)
            })
            .padding()

            Button {
                self.isPopupView_4.toggle()
                
            } label: {
                Text("ColorSliderHSBView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_4, content: {
                ColorSliderHSBView(isPopupView_4: $isPopupView_4)
            })
            .padding()

            Button {
                self.isPopupView_5.toggle()
                
            } label: {
                Text("NavigationListView")
                    .font(.title2)
            }
            .sheet(isPresented: $isPopupView_5, content: {
                NavigationListView(isPopupView_5: $isPopupView_5)
            })
            .padding()
        }
    }
}

#Preview {
    ContentView()
}

 

ColorPickerView、ColorSliderHSBView と同様に View を呼び出す際、

モーダル表示をさせる sheet() を指定しました。

 

NavigationListView:ナビゲーション画面遷移

ナビゲーション画面遷移を行うアプリケーションを作ってみます。

 

ソース例:NavigationListVeiw

ContntVeiw(親画面)から呼び出される NavigationListVeiw(子画面)の

ソースを紹介します。

 


import SwiftUI

struct NavigationListView: View {

    @Binding var isPopupView_5: Bool

    var navi_lists = [
        "SwipeView",
        "CarouselView",
        "TabView",
        "TabBarView"
    ]

    var body: some View {
        VStack {

            NavigationStack {

                List(navi_lists, id: \.self) { navi_list in

                    NavigationLink(navi_list, value: navi_list)
                        .font(.system(size: 22))

                }
                .navigationDestination(for: String.self) { navi_list in

                    switch (navi_list) {

                    case "SwipeView":
                        Text(navi_list)
                            .font(.system(size: 22))
                            .foregroundColor(.blue)
                            .padding()

                    case "CarouselView":
                        Text(navi_list)
                            .font(.system(size: 22))
                            .foregroundColor(.pink)
                            .padding()
                        
                    case "TabView":
                        Text(navi_list)
                            .font(.system(size: 22))
                            .foregroundColor(.green)
                            .padding()

                    case "TabBarView":
                        Text(navi_list)
                            .font(.system(size: 22))
                            .foregroundColor(.orange)
                            .padding()

                    default:
                        Text(navi_list)
                            .font(.system(size: 22))
                            .foregroundColor(.blue)
                            .padding()

                    }
                }
                .navigationTitle("NavigationList")
                .font(.system(size: 22))
                .foregroundColor(.purple)
            }
        }

        Button(action: {
            withAnimation {
                self.isPopupView_5.toggle()
            }
        }, label: {
            Text("Close")
                .font(.title2)
                .foregroundColor(.black)
        })
        .padding()
    }
}

#Preview {
    NavigationListView(isPopupView_5: .constant(false))
}

  • var navi_lists = [“SwipeView”, “CarouselView”, “TabView”, “TabBarView”]
    :ナビゲーションで、画面遷移するメニュー名を設定しています。
  • NavigationStack {:ナビゲーション画面遷移を設定しています。
  • List(navi_lists, id: \.self) { navi_list in:リストに navi_lists の内容を、上から順番に設定しています。
  • NavigationLink(navi_list, value: navi_list):画面遷移のリンク先を設定しています。
  • .navigationDestination(for: String.self) { navi_list in:画面遷移先のViewを設定しています。
  • switch (navi_list) {:リストで選択された時の分岐を、設定しています。
  • case “SwipeView”: Text(navi_list):リストで選択されたメニュー名を、テキストで表示しています。テキストには、リストで選択された navi_list を渡して表示しています。
  • 今回は、どのリストを選択しても、簡単にテキストを表示しています。

 

 

アプリ実行:シミュレータ起動

では、実際にアプリを実行してみます。

Xcode の上部タブメニューより、Product → Run を選択するか、command + R を

押してみて下さい。

 

エラーが無ければ、iPhoneシミュレータが起動します。

 

ContntVeiw(メインメニュー)に追加した NavigationListViewボタンが

表示されている事が確認出来ました。

 

 

NavigationListView:起動画面

では、NavigationListViewボタンを押してみます(タップします)。

 

前回、作成した ColorSliderHSBView(色スライダ調整アプリ)と同様に、

ContntVeiw(メインメニュー)の上に NavigationListVeiw(ナビゲーション機能)が

重なって、表示された事が確認出来たと思います。

 

NavigationList の内容は、下記の通りです。

  • SwipeView
  • CarouselView
  • TabView
  • TabBarView

 

NavigationListを選択

では、実際に NavigationList を選択してみます。

先ずは、NavigationList の上段の SwipeView を押してみます(タップします)。

 

 

NavigationList の上段の SwipeView を押す(タップする)と、左から右へ

画面遷移を行い、SwipeView のテキストが表示されたと思います。

では、NavigationList に戻ってみます。

 

 

NavigationStack は、戻るボタンの制御を記述しなくても、自動的に戻るボタンを設定します。

画面の左上の「<」(赤枠)を押す(タップする)と、NavigationLink へ戻ります。

 

画面の下にあるCloseボタン(青枠)を押す(タップする)と、ContntVeiw(メインメニュー)

に戻ってしまいますので、ご注意下さい。

 

次に、NavigationList の2段目の CarouselView を押してみます(タップします)。

 

 

NavigationList の2段目の CarouselView を押す(タップする)と、左から右へ

画面遷移を行い、CarouselView のテキストが表示されたと思います。

 

画面の左上の「<」を押して(タップして)、NavigationLink へ戻ります。

今度は、NavigationList の3段目の TabView を押してみます(タップします)。

 

 

NavigationList の3段目の TabView を押す(タップする)と、左から右へ

画面遷移を行い、TabView のテキストが表示されたと思います。

 

画面の左上の「<」を押して(タップして)、NavigationLink へ戻ります。

最後に、NavigationList の4段目の TabBarView を押してみます(タップします)。

 

 

NavigationList の4段目の TabBarView を押す(タップする)と、左から右へ

画面遷移を行い、TabBarView のテキストが表示されたと思います。

 

遷移コントロール

NavigationStack には、下記の3種類の画面遷移が用意されていましたね。

  1. 直接遷移:リンクやボタンを押すことで、直接、画面遷移を実現します。(NavigationStack+NavigationLink)
  2. 遷移コントロール:リンクやボタンを押すことで、押したリンクの結果を受けて、画面遷移を一箇所でコントロールします。(NavigationStack+NavigationLink+navigationDestination)
  3. 配列コントロール:画面の遷移状況を管理する配列(path)を用意し、配列操作の結果を受けて、画面遷移を一箇所でコントロールします。(NavigationStack(path: $path)+navigationDestination)

今回の記事では、上記から、2:遷移コントロールを実現する為に、押したリンクの結果を

受けて、画面遷移を一箇所でコントロールしました。

 

まとめ

今回は、SwiftUIで、NavigationStack を利用してナビゲーション画面遷移を行う

アプリケーションを開発する記事を紹介しました。

 

次回は、SwiftUIで、写真などの画像をスワイプ(スライド)させて移動させたり、

画像をピンチイン・ピンチアウト(縮小・拡大)するアプリケーションを開発する記事を

紹介しようと思います。

コメント

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