【Swift UI】NavigationStackの使い方!iOS16以降の画面遷移方法

【Swift UI】NavigationStackの使い方!iOS16以降の画面遷移方法

この記事からわかること

  • SwiftUINavigationStackとは?
  • iOS16以降で画面遷移させる方法
  • ナビゲーションバーカスタマイズするには?
  • NavigationSplitViewとは?

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

参考文献:Migrating to new navigation types

これまで使用していたNavigationView構造体はiOS13.0〜16.0はDeprecated(非推奨)になったのでその代わりにNavigationStackNavigationSplitViewの2つの構造体への置き換えが推奨されているので今回はNavigationStackの使い方をまとめておきたいと思います。

NavigationStack構造体

公式リファレンス:NavigationStack構造体

@MainActor  struct NavigationStack<Data, Root> where Root : View

NavigationStackは、非推奨となったNavigationViewの代わりに用意されたスタック(積み重ねる)構造で管理された画面遷移を実装できる構造体です。スタック構造の遷移情報は基本的に後入れ先出し(LIFO: Last In First Out; FILO: First In Last Out)で操作されます。大元となるルートビューを起源にビューを上に追加したり、ビューを削除することでViewの遷移を実装しています。

基本的な使い方はNavigationViewと変わらず、NavigationStackでビューを囲むことで中にあるビューを管理対象にすることができます。色々変化している部分も多いので使用方法をまとめておきます。

NavigationStack {
  // View
}

特にnavigationViewStyle(.stack)の使用はNavigationStackへの移行が推奨されています。

NavigationView {
    /* content */
}
.navigationViewStyle(.stack)

画面遷移の方法

これまで通り画面遷移にはNavigationStack内でNavigationLink構造体を使用します。使用方法は変わらないので遷移先のビューとラベルを表示することでリンクボタンを実装することができます。非推奨になっているイニシャライザもあるので注意してください。

おすすめ記事:【Swift UI】NavigationLinkの使い方!navigationDestinationとの組み合わせ

NavigationStack {
    NavigationLink {
        // 遷移先のビューを指定
        MyNextView()
    } label: {
        // リンクボタンのテキストを指定
        Label("MyNextViewへ", systemImage: "arrowshape.turn.up.right.fill")
    }
}

また遷移情報は上記の場合、可視化できていませんが、init(path:root:)を使用することで遷移情報を可視化し、管理、操作しやすくすることも可能です。

Navigationをカスタマイズするモディファイア

NavigationViewの時にNavigationをカスタマイズするために使用していたnavigationTitleなどのモディファイアはViewを拡張して定義されているので変わらず呼び出して使用することができます。

extension View {
    public func navigationTitle(_ title: Text) -> some View
}

Navigationをカスタマイズするモディファイアを役割ごとにまとめていきます。

タイトルを付与する

ナビゲーションバーにタイトルを付与するにはnavigationTitleモディファイアを使用します。

NavigationStack {
    List {
        Text("要素1")
        Text("要素2")
        NavigationLink("リンク1") {
            MyNextView()
        }
    }.navigationTitle("タイトル")
}
【SwiftUI】NavigationViewの使い方!タイトルを付与する

またタイトルを付与したことで遷移後の画面の「Back」ボタンもタイトル名のボタンへと変更されます。

ナビゲーションバー(タイトル)を非表示にする

タイトルを非表示にするにはnavigationBarHiddenモディファイアを使います。

NavigationStack {
    List {
        Text("要素1")
        Text("要素2")
        NavigationLink("リンク1") {
            MyNextView()
        }
    }.navigationTitle("タイトル")
    .navigationBarHidden(true)
}

toolbar(_:for:)で非表示にする

navigationBarHiddenモディファイアはiOS16以降非推奨になったのでナビゲーションバーを非表示するにはtoolbar(_:for:)モディファイアを使用します。

.toolbar(.hidden, for: .navigationBar)

「Back」ボタンを非表示にする

ナビゲーションバーにデフォルトで表示される「Back」ボタンを表示させたくない場合は子View側にnavigationBarBackButtonHiddenモディファイアを使えば非表示にすることができます。

struct MyNextView: View {
    var body: some View {
        Text("MyNextView")
            .navigationTitle("MyNextView")
            .navigationBarBackButtonHidden(true)
    }
}

画面遷移のタイミングを変数の値とリンクさせる

navigationDestinationモディファイアを使用することで画面遷移のタイミングを変数の値が変化した時に実行することができます。

struct TestNavigationView: View {
    @State  var isPresented:Bool = false
    var body: some View {
        NavigationStack {
            Button {
                isPresented = true
            } label: {
                Text("MyNextView")
            }.navigationDestination(isPresented: $isPresented) {
                MyNextView()
            }
        }
    }
}

NavigationSplitView構造体

公式リファレンス:NavigationSplitView構造体

struct NavigationSplitView<Sidebar, Content, Detail> where Sidebar : View, Content : View, Detail : View

ちなみにNavigationSplitViewiPadなどの大画面のデバイスで使用される、2つのViewを並べた画面を実現するための構造体です。例えば以下のように使用してiPadアプリで分割したビューを構築することができます。

import SwiftUI

struct TestNavigationView: View {
    let users: [User] = [
        User(name: "Ame", greeting: "こんにちは"),
        User(name: "Kasa", greeting: "Hello"),
        User(name: "Mahiro", greeting: "コンニチハ")
    ]
    @State  private var selectedUser: User?

    var body: some View {
        NavigationSplitView {
            MasterView(users: users, selectedUser: $selectedUser)
            } detail: {
                DetailView(user: selectedUser)
            }
    }
}

struct MasterView: View {
    let users:[User]
    @Binding  var selectedUser: User?

    var body: some View {
        List(users) { user in
            Button(action: { selectedUser = user }) {
                Text(user.name)
            }
        }
        .navigationTitle("Users")
    }
}

struct DetailView: View {
    let user: User?

    var body: some View {
        if let user = user {
            Text(user.greeting)
                .navigationTitle(user.name)
        } else {
            Text("No item selected")
                .navigationTitle("Details")
        }
    }
}

struct User: Identifiable {
    let id = UUID()
    let name: String
    let greeting:String
}
【Swift UI】NavigationStackの使い方!iOS16以降の画面遷移方法

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index