Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Clearing Binding text to textfield still shows text in textfield

I have a textField and next to it a button that should clear the text. My problems is though that the TextField View only carries a binder. Hence the actual text in the textfield isn’t deleted since Bindings doesn’t reload views.

I tried to narrow it down as much as possible in an example:

 struct ContentView: View {
    
    @State var presentedView = false
    @State var text: String = ""
    
    var body: some View {
        Button("Hello, world!") { presentedView = true }
            .padding()
            .sheet(isPresented: $presentedView, content: {
                SomeView(viewModel: .init(textBinder: $text), text: $text)
            })
    }
}

struct SomeView: View {
    
    let viewModel: ViewModel
    @Binding var text: String
    
    var body: some View {
        HStack {
            TextFieldTyped(text: $text)
            Spacer()
            Button("erase") {
                $text.wrappedValue = ""
            }
        }
    }
    
    struct ViewModel {
        let textBinder: Binding<String>
    }
}

struct TextFieldTyped: UIViewRepresentable {
    @Binding var text: String

    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField(frame: .zero)
        textField.delegate = context.coordinator
        return textField
    }

    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.becomeFirstResponder()
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: TextFieldTyped

        init(_ textField: TextFieldTyped) {
            self.parent = textField
        }
        
        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            if (textField.text?.count ?? 0) == 1, string.isEmpty {
                parent.text = string
            } else if string.isEmpty, !(textField.text ?? "").isEmpty {
                parent.text = String(textField.text?.dropLast() ?? "")
            } else {
                parent.text = (textField.text ?? "").isEmpty ? string : (textField.text ?? "") + string
            }
            return true
        }
    }
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

try the following code without the useless ViewModel, and an update of text in updateUIView:

struct ContentView: View {
    @State var presentedView = false
    @State var text: String = ""
    
    var body: some View {
        Button("Hello, world!") { presentedView = true }
        .padding()
        .sheet(isPresented: $presentedView, content: {
            SomeView(text: $text)
        })
    }
}

struct SomeView: View {
    @Binding var text: String
    
    var body: some View {
        HStack {
            TextFieldTyped(text: $text)
            Spacer()
            Button("erase") {
                text = ""  // <--- here
            }
        }
    }
}

struct TextFieldTyped: UIViewRepresentable {
    @Binding var text: String
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField(frame: .zero)
        textField.delegate = context.coordinator
        return textField
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.becomeFirstResponder()
        uiView.text = text  // <--- here
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: TextFieldTyped

        init(_ textField: TextFieldTyped) {
            self.parent = textField
        }
        
        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            if (textField.text?.count ?? 0) == 1, string.isEmpty {
                parent.text = string
            } else if string.isEmpty, !(textField.text ?? "").isEmpty {
                parent.text = String(textField.text?.dropLast() ?? "")
            } else {
                parent.text = (textField.text ?? "").isEmpty ? string : (textField.text ?? "") + string
            }
            return true
        }
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading