SwiftUI TextField does not update its displayed text when I transform input inside a custom Binding

I’m trying to transform user keyboard input in a TextField so that, for example, whenever the user types the letter "a" it is stored and shown as the Greek letter "α". I created a custom Binding to intercept and modify the typed text before saving it to my observable model.

Here’s a simplified version of my code:

import SwiftUI

class User: ObservableObject {
    @Published var username: String = ""
}

struct ContentView: View {
    @ObservedObject var user = User()

    var usernameBinding: Binding<String> {
        Binding(
            get: { user.username },
            set: { newValue in
                // Replace all "a" with "α"
                user.username = newValue.replacingOccurrences(of: "a", with: "α")
            }
        )
    }

    var body: some View {
        TextField("Username", text: usernameBinding)
            .padding()
            .onChange(of: user.username) { newValue in
                print("username changed to:", newValue)
            }
    }
}

When I type "a", I can see in the console that the onChange handler prints the transformed string ("α"), and the model (user.username) is updated. However, the TextField on screen still shows the original "a" instead of updating to "α" immediately.

I expected the text field to update its displayed value whenever the bound property changes (since username is @Published on an ObservableObject), but that doesn’t seem to happen when I modify the text in the binding’s set closure.

Is this a known limitation of SwiftUI TextField?

Is there a better way to transform user input so the field shows the transformed text based on some processing?

Any advice or explanation would be appreciated.

SwiftUI TextField does not update its displayed text when I transform input inside a custom Binding
 
 
Q