TextField with NumberFormatter, bound to Decimal property with Xcode > 13 beta 2.

The NumberFormatter seems to stop working with Decimal type properties since Xcode version 13 beta 3 (13A5192j).

The following code works up to Xcode version 13 beta 2 and then no longer.

Question:

What must be changed in the code so that entered numerical values are stored in the Decimal property again?

Code Example

import SwiftUI

struct Model {
  var decimalQuantity: Decimal = 2.43
  var someText: String = ""
}

struct DecimalBindingView: View {
  @Binding var model: Model
   
  private let numberFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.generatesDecimalNumbers = true
    return formatter
  }()
   
  var body: some View {
    Form {
      Section {
        Label {
          Text("This text field does not work correctly. \nIt doesn't write the value back to the property when the field loses focus or you click Enter.")
        } icon: {
          Image(systemName: "xmark.circle").foregroundColor(Color.red).scaleEffect(1.4)
        }
        .lineLimit(10)
         
        // The formatter or the two-way data binding does not seem to work.
        // The new value is not written back to the property correctly.
        // Question: What needs to be changed to make this work?
        TextField(
          "Input a number of type decimal…",
          value: $model.decimalQuantity,
          formatter: numberFormatter)
      }
      Section {
        TextField(
          "Sample field, so you can leave the other field",
          text: $model.someText)
      }
    }
  }
}

Minimal Xcode Project

https://github.com/brads-dev-dojo/SwiftUITextFieldWithDecimalValueTypeApp

An interesting example. In my opinion, this is a bug of iOS 13 beta 3+ and you should better send a bug report soon.


What must be changed in the code so that entered numerical values are stored in the Decimal property again?

As far as I tried, creating a Binding String <-> Decimal seemed nearly working:

private let decimalFormatter: NumberFormatter = {
//    let formatter = MyNumberFormatter()
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.generatesDecimalNumbers = true
    return formatter
}()

struct DecimalBindingView: View {
    @Binding var model: Model
    
    var stringBinding: Binding<String>
    
    init(model: Binding<Model>) {
        _model = model
        stringBinding = Binding(get: {
            decimalFormatter.string(for: model.wrappedValue.decimalQuantity) ?? ""
        }, set: {
            if let decimal = decimalFormatter.number(from: $0) as? NSDecimalNumber {
                model.wrappedValue.decimalQuantity = decimal as Decimal
            }
        })
    }
    
    var body: some View {
        Form {
            Section {
                Label {
                    Text("This text field does not work correctly. \nIt doesn't write the value back to the property when the field loses focus or you click Enter.")
                } icon: {
                    Image(systemName: "xmark.circle").foregroundColor(Color.red).scaleEffect(1.4)
                }
                .lineLimit(10)
                
                TextField("Input a number of type decimal…", text: stringBinding)
            }
            Section {
                TextField(
                    "Sample field, so you can leave the other field",
                    text: $model.someText)
            }
        }
    }
}

I opened a case with incident id FB9471568 via Feedback Assistant on 08 August 2021 and am now hoping for a response from Apple.

The problem still exists in the new Xcode version 13.0 beta 5 (13A5212g).

The problem still exists in the current Xcode Version 13.0 (13A233).

Unfortunately, the issue has remained in the Feedback Assistant without an answer. Dear Apple team. Do you plan to restore this feature, or can you suggest a workaround?

This issue also found storyboard textField, numberFormatter, and Decimal Style selection. I open lagacy project on Xcode13, build, then comma separator does not work.

As a simple workaround, you could try this:

		struct DecimalBindingView: View {
  			@State private var txt = "" 
  			....

            TextField("Input a number of type decimal…", text: $txt)
              .onChange(of: txt) { val in
                  if let dec = Double(val) {
                      model.decimalQuantity = Decimal(dec)
                  }
              }
                ...
            }

Good news!? macOS 12.0.1 Monterey based build shows good decimal format results. Xcode is still Version 13.0, 13A233. Its' funny experiences but I have to say OK. It's only checked on storyboard, I'm not sure SwiftUI.

TextField with NumberFormatter, bound to Decimal property with Xcode &gt; 13 beta 2.
 
 
Q