Diego Gonzalez
Diego Gonzalez

Reputation: 133

Swift UI | Textfield not reading entered value

I have a textfield which is supposed to log the units of a food product someone has eaten, which is then used to calculate the total number of calories, protein, etc. that the user consumed. But when the value is entered on the textfield, the units variable isn't updated. How can I fix this?

This is my code:

@State var selectFood = 0
@State var units = 0
@State var quantity = 1.0
    
@State var caloriesInput = 0.0
@State var proteinInput = 0.0
@State var carbsInput = 0.0
@State var fatsInput = 0.0

var body: some View {
    VStack {
        
        Group {
            Picker(selection: $selectFood, label: Text("What did you eat?")
                    .font(.title)
                    .fontWeight(.bold)
                    .foregroundColor(.white))
            {
                ForEach(database.productList.indices, id: \.self) { i in
                    Text(database.productList[i].name)
                }
            }
            .pickerStyle(MenuPickerStyle())
                
            Spacer(minLength: 25)
                
            Text("How much did you have?")
                .font(.headline)
                .fontWeight(.bold)
                .foregroundColor(.white)
                .frame(alignment: .leading)

            //Textfield not working.
            TextField("Units", value: $units, formatter: NumberFormatter())
                .padding(10)
                .background(Color("Settings"))
                .cornerRadius(10)
                .foregroundColor(Color("Background"))
                .keyboardType(.numberPad)
                
            Button (action: {
                self.quantity = ((database.productList[selectFood].weight) * Double(self.units)) / 100
                    
                caloriesInput = database.productList[selectFood].calories * quantity
                proteinInput = database.productList[selectFood].protein * quantity
                carbsInput = database.productList[selectFood].carbs * quantity
                fatsInput = database.productList[selectFood].fats * quantity
                    
                UIApplication.shared.hideKeyboard()
                    
            }) {
                ZStack {
                    Rectangle()
                        .frame(width: 90, height: 40, alignment: .center)
                        .background(Color(.black))
                        .opacity(0.20)
                        .cornerRadius(15)
                                    ;
                    Text("Enter")
                        .foregroundColor(.white)
                        .fontWeight(.bold)
                } 
            } 
        }
    }
}

Upvotes: 0

Views: 180

Answers (1)

lorem ipsum
lorem ipsum

Reputation: 29614

This is an issue with NumberFormatter that has been going on for a while. If you remove the formatter it updates correctly.

This is a workaround. Sadly it requires 2 variables.

import SwiftUI

struct TFConnection: View {
    @State var unitsD: Double = 0
    @State var unitsS = ""
    
    var body: some View {
        VStack{
            //value does not get extracted properly
            TextField("units", text: Binding<String>(
                        get: { unitsS },
                        set: {
                            if let value = NumberFormatter().number(from: $0) {
                                print("valid value")
                                self.unitsD = value.doubleValue
                            }else{
                                unitsS = $0
                                //Remove the invalid character it is not flawless the user can move to in-between the string
                                unitsS.removeLast()
                                print(unitsS)
                            }
                        }))
            
            Button("enter"){
                print("enter action")
                print(unitsD.description)
            }
        }
    }
}

struct TFConnection_Previews: PreviewProvider {
    static var previews: some View {
        TFConnection()
    }
}

Upvotes: 1

Related Questions