I have an Observable Object that is tracking several doubles. They are linked to TextFields in my ContentView.
I discovered that I could link them using value: and formatter: instead of text:
TextField( "Double Value", value: $OO.myFirstDouble, formatter: NumberFormatter.decimal )
extension NumberFormatter {
static var decimal: NumberFormatter {
let formatter = NumberFormatter()
formatter.minimumFractionDigits = 3
formatter.numberStyle = .decimal
return formatter
}
}
The problem is that when you enter anything into the fields, the data does not propagate to the observable object Unless you click "return" on the keyboard. To make matters more exciting, decimalPad and numberPad don't have an enter key by default (I haven't gotten to that part yet).
If you use text:
TextField( "Double Value", text: $OO.myFirstDouble )
Then the data propagates with every entry or removal of a number
Running around in circles (because I was not smart enough to start git) I played with some things.
Have my Observable Object accept the strings for data, then create parallel calculated variables that convert the string to double when needed.
struct ContentView: View {
@ObservedObject var tvm = OO()
var body: some View {
TextField("Present", text: $OO.myFirstDouble )
}
}
class OO: ObservableObject {
@Published var myFirstDouble: String = "0"
var firstDouble: Double {
get {
if let tmp: Double = Double(myFirstDouble) {
return tmp
}
return 0
}
set(newValue) {
myFirstDouble = String(format: "%0.4f", firstDouble)
}
}
}
That seems like an ugly solution.. But someone somewhere said we have ways of making this a little more compact...
So I tried building a class
class myStingyDouble {
var value: Double
var string: String {
didSet {
if let tmp: Double = Double(string) {
value = tmp
}
}
}
var format: String
var name: String
init(name: String, value: Double, format: String) {
self.string = String(format: format, value)
self.value = value
self.name = name
self.format = format
}
func set(value: Double) {
self.value = value
self.string = String(format: self.format, value)
}
}
but then that text field in the content view looked like
TextField( "Double Value", text: $OO.firstDouble.string )
This actually updated the OO without any problem. But when I used the values to calculate something and updated the OO within itself updating the myStringyDouble object, the data did not send back to the TextView...
Right now I have the cludgy version working. I have found references that suggest that multiple class levels are not supported yet in the Observable Object version.
The simple answer would be for the value:formatter version to work (and I think it is the "right" path). It is the wrong path because the user shouldn't have to figure out how to make a "return" happen.
(First post, apologies if I violated any rules...)