Updated to simplify example
I want to change the title text, when either I type in the textfield or tap the button. However I don't want to change the TextField text when I tap the button, just want to change the title text. This is the demo code
struct HobbitView: View {
@State private var hobbitName = "Bilbo"
var body: some View {
//"Place Holder" should not be modified by tapping the button
TextField("Place Holder", text: $hobbitName)
//Should be modifiable by TextField or Button
Text("The name is \(hobbitName).")
//Should only modify the Text, not the TextField text
Button("Set a Name") {
hobbitName = "Sam"
}
}
}
I guess you may call it "conditional binding". I don't know how else to call it.
I'm new to SwiftUI and I think I'm missing some key knowledge on how SwiftUI bindings work.
You need an additional @State
to store the text field's text.
Set this to hobbit.firstName
initially, and when it changes, update hobbit.firstName
.
@StateObject private var hobbit = Hobbit()
@State private var textFieldText = ""
var body: some View {
TextField("Place Holder", text: $textFieldText)
.padding(.bottom)
.onAppear {
textFieldText = hobbit.firstName
}
.onChange(of: textFieldText) { _, newValue in
hobbit.firstName = newValue
}
Text("The name is \(hobbit.firstName).")
.font(.title)
Button("Set a Name") {
hobbit.firstName = "Sam"
}
}
You can wrap this into a custom TextField
:
struct HobbitView: View {
@StateObject private var hobbit = Hobbit()
var body: some View {
CustomTextField(text: $hobbit.firstName)
Text("The name is \(hobbit.firstName).")
.font(.title)
Button("Set a Name") {
hobbit.firstName = "Sam"
}
}
}
struct CustomTextField: View {
@State private var textFieldText = ""
@Binding var text: String
var body: some View {
TextField("Place Holder", text: $textFieldText)
.padding(.bottom)
.onAppear {
textFieldText = text
}
.onChange(of: textFieldText) { _, newValue in
text = newValue
}
}
}