SwiftUI TextField with optional value working for @State but not @Binding properties

I've encountered a potential bug where a TextField connected to an optional value (not a string) works as expected when bound to a @State property, but won't update a @Binding property.

Here is some example code

import SwiftUI

struct ContentView: View
{
	@Binding var boundValue: Double?
	@State private var stateValue: Double? = 55

	var body: some View
	{
		TextField("Bound value", value: $boundValue, format: .number)
		Text("\(boundValue ?? .nan)")
		TextField("State value", value: $stateValue, format: .number)
		Text("\(stateValue ?? .nan)")
	}
}

#Preview
{
	ContentView(boundValue: .constant(42.00))
}

It's as though the optional value stored externally is preventing the value updating. Can anyone confirm whether this is intentional, or a bug?

This is in Xcode 26b6, on macOS Tahoe 26b8, but from this query it looks like the problem has existed for years.

May be I missed something of your intent.

Why using a Binding here ? That means ContentView is called from another view with a Sate var ?

Otherwise, it is a misuse of Binding.

I changed to this, which works.

struct ContentView: View {
    @State var boundValue: Double?
    @State private var stateValue: Double? = 55
 
    var body: some View {
        CallTextField(boundValue: $boundValue)
//        TextField("Bound value", value: $boundValue, format: .number)
        Text("\(boundValue ?? .nan)")
        TextField("State value", value: $stateValue, format: .number)
        Text("\(stateValue ?? .nan)")
    }
}

struct CallTextField: View {
    @Binding var boundValue: Double?

    var body: some View {
        TextField("Bound value", value: $boundValue, format: .number)
    }
}

Thanks for making the effort to answer.

The code I posted was simply to demonstrate the inconsistency. In my actual project there's a model instantiated by the main file, with bound properties passed into the subviews.

As such, I can't replace the binding with a local state.

Looking at your code, it's interesting that the boundValue var you've done in the subview does work. I'll have to do some trial and error to figure out what's causing the difference. (Only immediate difference I can see is in your code, the bound value is being created in a View.)

A Binding is a value that has to be passed to someone. In other words, it has to be bound to something. It does not "exist" per se.

See here, which is similar to the code I posted. https://developer.apple.com/documentation/swiftui/binding

So, IMHO, that's not a bug, that's a SwiftUI feature.

I think we're getting a bit distracted here.

@Binding exists and has many valid uses. The issue I am encountering is that a passed in binding isn't getting updated by a TextField, while a @State binding does work.

It's either a bug or it's by design. That is the question I'm wanting to get an answer to. I can't think of it being by design as it displays the value fine, just not update it.

passed in binding

Yes, and that was my initial question: to what is it passed ?

But I'll let more skilled SwiftUI experts reply.

Yes, and that was my initial question: to what is it passed ?

The question confused me. You were talking about the binding being passed to something. But clearly it's being passed to the TextField, so I figured I must be misunderstanding what you were meaning.

Have a look here: https://www.appypievibe.ai/blog/working-with-binding-in-swiftui#:~:text=In%20SwiftUI%2C%20you%20can%20create,and%20also%20stores%20its%20value

or here: https://stackoverflow.com/questions/59247183/swiftui-state-vs-binding

Binding does not cause the View to update the body, which State does.

So, it's normal it is nor updated.

You can see that boundValue is not updated by adding onSubmit:

        TextField("Bound value", value: $boundValue, format: .number)
            .onSubmit {
                print("Textfield submitted", boundValue)
            }

I'd like to say that I genuinely appreciate the effort you're making to help me out. I don't want you to feel that I'm ungrateful.

Having said that, I can't see where you're getting the information that Binding doesn't cause a view to update. That's the whole purpose of a binding.

The difference between State and Binding, is where the data is 'owned'. While the syntax has changed a few times over the years, currently State declares where the data is instantiated and held. Binding declares the data is owned elsewhere, and "loaned" to the subviews with a 2-way binding to the parent.

In any case, as it turns out, the problem in my demo code was me using .constant() in the preview (so the value wasn't changing).

The optional binding does work when I alter the demo code to use a state value in the parent code. I'm going to have to do some more investigation to why it's not working in my full app, then try to simplify from there.

SwiftUI TextField with optional value working for @State but not @Binding properties
 
 
Q