0
import SwiftUI

struct ChildView: View {
    let entryLabel : String
    @Binding var date : Date?
    
    var body: some View {
        HStack(spacing:20) {
            Text(entryLabel)
                .font(.title3)
            Spacer()
            Button("Add Date") {
                date = Date.now
                print("add \(date)")
            }
            .buttonStyle(.bordered)
        }
        .padding(.horizontal,5)
        .padding(.vertical,10)
    }
}

struct ChildDateView_Previews: PreviewProvider {
    static var previews: some View {
        @State var date : Date?
        VStack {
            ChildView(entryLabel: "The label", date: $date)
            let s = date?.formatted() ?? "No Date"
            Text(s)
        }
        .onChange(of: date) { newValue in
            print("changed")
        }
    }
}

Above simple view, idea is that pressing the button will set the binding date with a value of the current date. But the binding value never changes from nil. Only get "add nil" printed in the console. And of course the onChange never fires. Guessing it has to be something stupid on my part but I simply cannot see it. What am I doing wrong here or not getting?

vagrant
  • 868
  • 1
  • 9
  • 23

1 Answers1

1

I put your ChildView in a fresh project and it works. Here's my ContentView:

import SwiftUI

struct ContentView: View {
    @State var date : Date?
    var s: String {
        date?.formatted() ?? "No Date"
    }
    var body: some View {
        VStack {
            ChildView(entryLabel: "The label", date: $date)
            Text(s)
        }
        .onChange(of: date) { newValue in
            print("changed")
        }
    }
}

Edit: So the problem is your preview.

from: SwiftUI preview provider with binding variables

Because the PreviewProvider protocol is a static protocol. From Apple docs: "Xcode statically discovers types that conform to the PreviewProvider protocol in your app, and generates previews for each provider it discovers." The static var previews can only access static variables.

Create a local @State static var:

struct ChildDateView_Previews: PreviewProvider {
    @State static  var date : Date?
    static var previews: some View {
        VStack {
            ChildView(entryLabel: "The label", date: $date)
            let s = date?.formatted() ?? "No Date"
            Text(s)
        }
        .onChange(of: date) { newValue in
            print("changed")
        }
    }
}
soundflix
  • 928
  • 9
  • 22
  • Thank you. You made me realize that I have to do the thing where you add a wrapper in the preview with the state rather than doing it directly if you want to have the @State be live. Described here already that I somehow missed in searches. https://stackoverflow.com/questions/60105438/swiftui-preview-provider-with-binding-variables – vagrant Jul 10 '23 at 11:56
  • I updated my answer with a working preview – soundflix Jul 10 '23 at 12:39