[SOLVED] SwiftUI custom textfield not getting updated value

Issue

I would like to create a custom text field with some input buttons, on click of those buttons text field should update the value accordingly.

I have multiple options to set value in InputView, so that if I edited InputView and if I click on any button, the button should update the value.

here is my code


@main
struct AmountApp: App {
    var body: some Scene {
        WindowGroup {
            InputView()
        }
    }
}
struct InputView: View {
    @State var value: Double = 0.00
    var body: some View {
        VStack {
            Text("Amount")
            TextInput(value: $value).padding(.horizontal)
            HStack(alignment: .center, spacing: 16) {
                Button { value = 20 } label: { Text("20") }
                Button { value = 30 } label: { Text("30") }
                Button { value = 40 } label: { Text("40") }
            }
            
            Button { print(value) } label: {
                Text("Print")
                    .padding(8)
                    .foregroundColor(.red)
            }
        }
    }
}


struct TextInput: UIViewRepresentable {
    @Binding var value: Double
    
    func makeCoordinator() -> Coordinator { Coordinator(self) }
    
    func updateUIView(_ uiView: UITextField, context: Context) { }
    
    func makeUIView(context: Context) ->  UITextField {
        let textfield = UITextField()
        textfield.placeholder = "Enter amount"
        textfield.text = "\(value)"
        textfield.keyboardType = .decimalPad
        textfield.setContentHuggingPriority(.defaultHigh, for: .vertical)
        textfield.setContentHuggingPriority(.defaultLow, for: .horizontal)
        textfield.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        return textfield
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: TextInput
        init(_ textField: TextInput) { self.parent = textField }
    }
}

Help would be greatly appreciated, ~Good day.!!

Solution

The binding value will not update if you don’t implement theUITextFieldDelegate method(s) to receive user input (SwiftUI Custom TextField with UIViewRepresentable Issue with ObservableObject and pushed View)

When you change the value from the SwiftUI side, your UIViewRepresentable needs to handle the change in updateUIView (pass the new value to UITextField)

Also remember to set textfield.delegate = context.coordinator so that you receive events.

struct TextInput: UIViewRepresentable {
    @Binding var value: Double
    
    func makeCoordinator() -> Coordinator { Coordinator(self) }
    
    // for handling swiftui-side modification to the binding (your buttons)
    func updateUIView(_ uiView: UITextField, context: Context) { 
        uiView.text = value
    }
    
    func makeUIView(context: Context) ->  UITextField {
        let textfield = UITextField()
        textfield.placeholder = "Enter amount"
        textfield.text = "\(value)"
        textfield.keyboardType = .decimalPad
        textfield.setContentHuggingPriority(.defaultHigh, for: .vertical)
        textfield.setContentHuggingPriority(.defaultLow, for: .horizontal)
        textfield.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        textfield.delegate = context.coordinator // set the delegate
        return textfield
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: TextInput
        init(_ textField: TextInput) { self.parent = textField }
        func textFieldDidEndEditing(_ textField: UITextField) {
            if let text = textField.text {
                parent.value = Double(text) ?? 0
            } else {
                parent.value = 0
            }
        }
    }
}

Answered By – atultw

Answer Checked By – Mary Flores (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.