🚪

NavigationViewとNavigationStack

2024/03/06に公開

📕Overview

SwiftUIの画面遷移をするときに、NavigationViewと呼ばれているものがありましたが、iOS16~NavigationStackが推奨されるようになったそうです。

今回は、何が変わったのかなぜ推奨しないのかについて解説していこうと思います。海外の動画で参考になるものがあったので、こちら参考にやっていきます。
https://www.youtube.com/watch?v=GZ-hQWMjT0s

🧷summary

SwiftUIでプロジェクトを作成して、以下のコードを書いてください。

NavigationViewを使った例

指定したページに画面遷移して値を渡す。

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: {
                // 画面遷移先のページを書く
                DetailView(value: 1)
            }, label: {
                Text("Click me")
            })
            .navigationTitle("画面遷移")
        }
    }
}

struct DetailView: View {
    
    let value: Int
    
    init(value: Int) {
        self.value = value
        print("詳細ページ: \(value)")
    }
    
    var body: some View {
        Text("Hi")
    }
}

#Preview {
    ContentView()
}
ForEachとScrollViewを使った例

rangeを使って、1~10未満の配列を生成して、スクロールできるようにしたコード。

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            ScrollView {
                VStack(spacing: 40) {
                    ForEach(1..<10) { x in
                        NavigationLink(destination: {
                            // 画面遷移先のページを書く
                            DetailView(value: x)
                        }, label: {
                            Text("Click me")
                        })
                    }
                    .navigationTitle("画面遷移")
                }
            }
        }
    }
}

struct DetailView: View {
    
    let value: Int
    
    init(value: Int) {
        self.value = value
        print("詳細ページ: \(value)")
    }
    
    var body: some View {
        Text("渡された値 \(value)")
    }
}

#Preview {
    ContentView()
}

このコードには、問題があってレンダリングのせいか2回呼ばれて9個の画面が表示されていることになっている???

NavigationLinkが遅延していないため、起きてしまう現象のようです!

NavigationStackを使った例

NavigationStackにコードを修正すると遅延して処理がおこなわれるようになるので、アプリのパフォーマンスが工場するみたいです。ビルドしたときに、複数の画面が呼ばれる初期化処理が実行されておりませんでした!

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationStack {
            ScrollView {
                VStack(spacing: 40) {
                    ForEach(1..<10) { x in
                        
                        NavigationLink(value: x) {
                            // 画面遷移先のページを書く
                            Text("Click me: \(x)")
                        }
                    }
                }
            }
            .navigationTitle("画面遷移")
            .navigationDestination(for: Int.self) { value in
                DetailView(value: value)
            }
        }
    }
}

struct DetailView: View {
    
    let value: Int
    
    init(value: Int) {
        self.value = value
        print("詳細ページ: \(value)")
    }
    
    var body: some View {
        Text("渡された値 \(value)")
    }
}

#Preview {
    ContentView()
}

logが出てこなかった?

🧑‍🎓thoughts

今回は、SwiftUIで画面遷移をするときに、NavigationViewとNavigationStackでどう違うのかについて記事を書いてみました。まさか他のページが呼ばれているとは....
iOS16からは、NavigationStackが推奨で、iOS16.1では、NavigationViewが非推奨になっておりました。移行作業も簡単なようなので対応はしやすいのかな。

参考になった記事:
https://dev.classmethod.jp/articles/ios16-swiftui-navigation-stack/

Discussion