'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
}
}
}
Solution 1:[1]
The other answer is perfectly fine but it is also good idea to pull related vars out into their own struct, as recommended in Data Essentials in SwiftUI (WWDC20) at 4:00. Here is how I think it would be achieved in your case:
struct SomeViewConfig {
var presented = false
var text: String = ""
mutating func present() {
presented = true
text = ""
}
}
struct ContentView2: View {
@State var someViewConfig = SomeViewConfig()
var body: some View {
Button("Hello, world!") { someViewConfig.present() }
.padding()
.sheet(isPresented: $someViewConfig.presented) {
SomeView(config: $someViewConfig)
}
}
}
struct SomeView: View {
@Binding var config: SomeViewConfig
var body: some View {
HStack {
TextFieldTyped(text: $config.text)
Spacer()
Button("erase") {
config.text = ""
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | malhal |
