Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass binding to child view in the new NavigationStack.navigationDestination

Tags:

swift

swiftui

I am trying to pass a binding from a parent list view into a child detail view. The child detail view contains logic to edit the child. I want these changes to be reflected in the parent list view:

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")
            }
        }
    }
}

But as you can see, I cannot pass number into ChildDetailView because it expects a binding. I have tried putting $ before number but that doesn't work either. Is there a way to make this work, or am I using the new NavigationStack completly wrong?

like image 899
P. Protas Avatar asked Sep 08 '25 15:09

P. Protas


1 Answers

Well, actually it is possible, but at first it is needed source of truth, i.e. state with data to bind to, and but in this case Binding will update only source, but not destination. It is more appropriate is to use ObservableObject view model in such case.

Tested with Xcode 14 / iOS 16

Note: binding do not refresh ChildDetailView in such case - in can be used only for actions, but source is updated !!

Here is main part:

@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 !!
        }
    }
}

and a couple of extensions needed for Binding to transfer via navigation link value.

Complete code on GitHub

like image 183
Asperi Avatar answered Sep 10 '25 12:09

Asperi