I have a custom SwiftUI binding where I convert a value before it's rendered in a TextField in my view. I do this because I want to convert the number of minutes (stored as an Int
in my database) to one of two time formats (HHMM or #.#).
app.flight
is a @Published
variable on an ObservableObject
in my view model. duration
is the Int
property of my object, and timeForm
is an extension that does the time conversion and returns the appropriate String
value.
Here's my binding:
let time = Binding(
get: {
app.flight.duration.timeForm //Converts the Int to a String
},
set: { $0 } <-- ???
)
...and here is my TextField
in my view where I use the time
binding:
TextField(timeDisplayHHMM ? "####" : "#.#", text: time, onCommit:{
print(time.wrappedValue) //<-- Prints the initial value from the binding's getter
})
I need the setter to finish setting the value of time
so that when I access it in my onCommit
, it has the latest value the user has entered. But as I have it, it's printing the original value from the binding's getter.
How do I make the set
statement in my binding pass on the set value so it's ready by the time I use it in onCommit
?
CodePudding user response:
you could try something like this approach:
struct ContentView: View {
@State var timeDisplayHHMM = true
@State var time = ""
@State var app_flight_duration: Int = 0 // <-- for testing
var body: some View {
VStack {
Text("time: " time)
Text("duration: \(app_flight_duration)")
TextField(timeDisplayHHMM ? "####" : "#.#",
text: Binding(
get: { time },
set: {
time = $0
// here convert to int,
// you need to do a lot more than this simple example
if let theInt = Int($0) {
app_flight_duration = theInt // assign to your model
}
}
),
onCommit:{
print("-----> time " time " app_flight_duration: \(app_flight_duration)")
})
}
}
}