中学英語808712 views
高校日本史189857 views
数学講師2852771 views
小学理科717236 views
世界の国560595 views
教育148875 views
ヒストリア284143 views
高校国語785655 views
いろは2986023 views
高校生物549842 views
Help
Tools

English

値ベースのナビゲーション(navigationDestination)

iOS 16 で導入された値ベースのナビゲーションは、navigationDestination を使ってデータの型に基づいた画面遷移を実現します。従来の NavigationLink よりも柔軟で、プログラム的な制御が容易になりました。

従来の NavigationLink との違い

従来の方法では、NavigationLink に直接遷移先のビューを指定していました。

// 従来の方法
NavigationLink("詳細") {
    DetailView(item: item)
}

値ベースのナビゲーションでは、NavigationLink に値を渡し、その値の型に対応する遷移先を navigationDestination で定義します。

// 値ベースの方法
NavigationLink("詳細", value: item)

// 別の場所で遷移先を定義
.navigationDestination(for: Item.self) { item in
    DetailView(item: item)
}

基本的な使い方

struct Item: Identifiable, Hashable {
    let id = UUID()
    var name: String
}

struct ContentView: View {
    let items = [
        Item(name: "りんご"),
        Item(name: "みかん"),
        Item(name: "バナナ")
    ]
    
    var body: some View {
        NavigationStack {
            List(items) { item in
                NavigationLink(item.name, value: item)
            }
            .navigationDestination(for: Item.self) { item in
                Text("\(item.name)の詳細画面")
                    .navigationTitle(item.name)
            }
            .navigationTitle("フルーツ")
        }
    }
}

値の型は Hashable に準拠している必要があります。

複数の型に対応

異なる型に対して、それぞれ異なる遷移先を定義できます。

struct User: Hashable {
    var name: String
}

struct Product: Hashable {
    var title: String
}

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                Section("ユーザー") {
                    NavigationLink("田中太郎", value: User(name: "田中太郎"))
                    NavigationLink("山田花子", value: User(name: "山田花子"))
                }
                
                Section("商品") {
                    NavigationLink("iPhone", value: Product(title: "iPhone"))
                    NavigationLink("MacBook", value: Product(title: "MacBook"))
                }
            }
            .navigationDestination(for: User.self) { user in
                UserDetailView(user: user)
            }
            .navigationDestination(for: Product.self) { product in
                ProductDetailView(product: product)
            }
        }
    }
}
型による分岐

navigationDestination は型ごとに定義できるため、同じリスト内で異なる種類のデータを扱える。

Hashable 必須

値として渡す型は Hashable に準拠している必要がある。Identifiable だけでは不十分。

遅延評価

遷移が実際に発生するまで、遷移先のビューは生成されない。

列挙型を使ったパターン

画面遷移のパターンを列挙型で定義すると、管理しやすくなります。

enum Destination: Hashable {
    case settings
    case profile(userId: Int)
    case article(articleId: Int)
}

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("設定", value: Destination.settings)
                NavigationLink("プロフィール", value: Destination.profile(userId: 123))
                NavigationLink("記事", value: Destination.article(articleId: 456))
            }
            .navigationDestination(for: Destination.self) { destination in
                switch destination {
                case .settings:
                    SettingsView()
                case .profile(let userId):
                    ProfileView(userId: userId)
                case .article(let articleId):
                    ArticleView(articleId: articleId)
                }
            }
        }
    }
}
従来の NavigationLink

遷移先を直接指定。シンプルだが、プログラム制御が難しい。

値ベースのナビゲーション

値を渡して型で遷移先を決定。path による制御が可能。

値ベースのナビゲーションは、複雑なナビゲーション構造を持つアプリで特に威力を発揮します。次の記事では、path を使ったプログラム的な画面遷移について解説します。