新しいNavigationStack.navigationDestinationで子ビューにバインディングを渡す方法 質問する

新しいNavigationStack.navigationDestinationで子ビューにバインディングを渡す方法 質問する

親リスト ビューから子詳細ビューにバインディングを渡そうとしています。子詳細ビューには、子を編集するためのロジックが含まれています。これらの変更を親リスト ビューに反映させたいです。

import SwiftUI

struct ParentListView: View {
    var body: some View {
        NavigationStack {
            List {
                ForEach(0 ..< 5) { number in
                    NavigationLink(value: number) {
                        Text("\(number)")
                    }
                }
            }
            .navigationDestination(for: Int.self) { number in
                ChildDetailView(number: number) //Cannot convert value of type 'Int' to expected argument type 'Binding<Int>'

            }
        }
    }
}

struct ChildDetailView: View {
    @Binding var number: Int
    var body: some View {
        VStack {
            Text("\(number)")
            Button {
                number += 10
            } label: {
                Text("Add 10")
            }
        }
    }
}

しかし、ご覧のとおり、バインディングが期待されるため、ChildDetailView に番号を渡すことはできません。番号の前に $ を付けてみましたが、それでも機能しません。これを機能させる方法はありますか、それとも新しい NavigationStack の使い方が完全に間違っていますか?

ベストアンサー1

実は可能ですが、まずは真実のソース、つまりバインドするデータのある状態が必要ですが、この場合、バインディングはソースのみを更新し、宛先は更新しません。このObservableObjectような場合は、ビュー モデルを使用する方が適切です。

Xcode 14 / iOS 16でテスト済み

注意: このような場合、バインディングは更新されませんChildDetailView。アクションにのみ使用できますが、ソースは更新されます。

主要部分は次のとおりです。

@State private var numbers = [1, 2, 3, 4, 5]  // << data !!
var body: some View {
    NavigationStack {
        List {
            ForEach($numbers) { number in      // << binding !!
                NavigationLink(value: number) {
                    Text("\(number.wrappedValue)")
                }
            }
        }
        .navigationDestination(for: Binding<Int>.self) { number in // << !!
            ChildDetailView(number: number)  // << binding !!
        }
    }
}

バインディングがナビゲーション リンク値を介して転送するために必要な拡張機能がいくつかあります。

GitHubの完全なコード

おすすめ記事