I have a SwiftData model with 2 optionals:
@Model
class MySet: Identifiable {
var id: UUID
var weight: Int?
var reps: Int?
I pass an object of this set down to this view where its reps and weight can be 0 if the set has not been edited yet:
struct SetEditor: View {
var currentIndex: Int
@Bindable var myset: MySet
Then I created an extension to allow me to bind it to a TextField:
//extensions to create bindings so the Textfield can directly manipulate the object
extension MySet {
var weightBinding: Binding<Int?> {
Binding<Int?>(
get: { self.weight },
set: { value in
if let value { //unwrapping the optional that the user entered and only setting it to weight if it isnt nil
self.weight = value
}
}
)
}
var repBinding: Binding<Int?> {
Binding<Int?>(
get: { self.reps },
set: { value in
if let value {
self.reps = value
}
}
)
}
}
Then I use it in a TextField like so :
TextField(
"(myset.weight ?? 0)",
value: myset.weightBinding, formatter: NumberFormatter()
)
this all worked perfectly fine before I made reps and weight optional (when a new set was created it was set to 0 0), but I wanted to save the user the step of having to clear the 0 to start typing, now when I add new numbers and click away from the TextField it no longer saves the number typed in it just reverst to nil nil, is there a way to fix this?
2
The issue was using NumberFormatter, to use Optional Binding Int? in TextFields in SwiftUi you must use the following:
TextField(
"(myset.weight ?? 0)",
value: myset.weightBinding, format: .number
)
Happy Coding
As you get
the optional from the model and set
a non-optional from the text field the Binding
must be the other way round
var weightBinding: Binding<Int?> {
Binding<Int?>(
get: { self.weight ?? 0 },
set: { self.weight = $0 }
)
}
var repBinding: Binding<Int?> {
Binding<Int?>(
get: { self.reps ?? 0 },
set: { self.reps = $0 }
)
}