UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

ObservableObject => TextField => Doubles

Forums > SwiftUI

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...)

2      

Google sent me down a variety of other paths...

    let myDouble = Binding<String>(get:{ OO.myFirstDouble.string}, set:{OO.myFirstDouble.string = $0} ) 

This also worked in one direction.

I tried to use the objectWillUpdate->send() concept, but that didn't seem to trigger.

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.