TextField does not accept input - TestFlight

I am a new developer and have been working on my app for several months. I have been testing in the simulator and on my personal device since the beginning of my development. I have finally got the app to a point where I am happy to release version 1, have paid my developer fee and can now test the app using TestFlight. I have successfully added my app to AppStore Connect and assigned to myself through TestFlight.

My issue is that the install from TestFlight does not take input in the TextFields of my form. The fields using NumberFormatting when tested from Xcode format 1,000 where the same field from TestFlight shows 1000.

In one case I allow the form to have optional data that is empty and still save, and when adding data to these optional fields, they are blank when saved.

In another case, I have data checking to bring focus to fields that cannot be empty before saving, and the form never allows me to save (as it thinks the fields are empty even though a value exists).

Is this a common issue that what is experienced in Xcode does not translate correctly to an App? A TextField is a pretty basic item and for it to work when tested directly but not via an App package in TestFlight has me stumped.

This is from the device using TestFlight

This is from the simulator in Xcode

As you can also see the Dividend Value is not calculating in the TestFlight version, but is working correctly in Xcode.

Any help is greatly appreciated

My issue is that the install from TestFlight does not take input in the TextFields of my form. The fields using NumberFormatting when tested from Xcode format 1,000 where the same field from TestFlight shows 1000.

It does not take the imput or it is not properly formatted ?

  • What input do you enter ?
  • What do you get ?
  • What did you expect ?

You should show the code. You may have a locale that is different in simulator and device

Note: when you paste image, don't forget to reduce the size, to avoid huge images.

It is easy to do:

when you import, you get a reference as:

("h t t p s://developer.apple.com/forums/content/attachment/7b2d017c-d4f1-4a79-bc93-55b73dc1c780" "title=6d01ce43-8b7a-4472-a2d2-4501dbb5f318.png;width=1170;height=2532")

Just edit to reduce the width and height, for instance dividing each by 4, to width=285;height=630"

Code for this view

struct CreateDividendView: View {
    @Environment(\.presentationMode) var presentationMode
    @Environment(\.colorScheme) var colorScheme
    @ObservedObject var exchange: StockExchange
    @ObservedObject var stock: Stock
    @StateObject var dividend = Dividend()
    @State private var showingAlert = false
    @State private var showingDateAlert = false
    var isNew = true

    var numberFormatter: NumberFormatter = {
        let nf = NumberFormatter()
        nf.locale = Locale.current
        nf.numberStyle = .decimal
        
        return nf
    }()

    var decimalFormatter: NumberFormatter = {
        let df = NumberFormatter()
        df.locale = Locale.current
        df.numberStyle = .decimal
        df.generatesDecimalNumbers = true

        return df
    }()

    var body: some View {
        NavigationView {
            VStack(spacing: 0) {
                HStack(spacing: 0) {

                    Text(stock.ticker)
                        .font(.title)
                        .bold()

                    Spacer()
                }
                .padding(.horizontal).padding(.horizontal, 5)

                HStack(spacing: 0) {

                    Text(stock.name.uppercased())
                        .font(.footnote)
                        .foregroundColor(.gray)

                    Spacer()
                }
                .padding(.horizontal).padding(.horizontal, 5)

                HStack(spacing: 0) {

                    Text("Dividend Value")
                        .padding(.leading, 10)

                    Spacer()

                    Text("$\(Double(dividend.quantity ?? 0) * (dividend.value ?? 0) - (dividend.fees ?? 0), specifier: "%.2f")")
                        .padding(.trailing, 10)
                }
                .padding(.horizontal, 10).padding(.vertical, 10)
                .background(Color(UIColor.systemGray2))
                .cornerRadius(8)
                .padding(.top, 20).padding(.horizontal, 20)

                Form {
                    HStack {
                        DatePicker("Date", selection: $dividend.date, displayedComponents: [.date])
                            .datePickerStyle(.compact)
                    }

                    HStack {
                        Text("Quantity")
                        TextField("100", value: $dividend.quantity, formatter: numberFormatter)
                            .multilineTextAlignment(.trailing)
                            .keyboardType(.numberPad)
                    }

                    HStack {
                        Text("Value")
                        TextField("1.234", value: $dividend.value, formatter: decimalFormatter)
                            .multilineTextAlignment(.trailing)
                            .keyboardType(.decimalPad)
                    }

                    HStack {
                        Text("Fees")
                        TextField("1.00", value: $dividend.fees, formatter: decimalFormatter)
                            .multilineTextAlignment(.trailing)
                            .keyboardType(.decimalPad)
                    }
                }

                if !isNew {
                    Button(action: {
                        showingAlert = true
                    }) {
                        Text("\(Image(systemName: "trash.fill"))  Delete Dividend")
                            .font(.title3)
                            .foregroundColor(.white)
                            .frame(width: UIScreen.main.bounds.width/1.2, height: 35, alignment: .center)
                            .padding(.horizontal, 10).padding(.vertical, 5)
                            .background(Color.red)
                            .cornerRadius(10)
                    }
                    .padding(8)
                }

                Spacer()
            }
            .navigationTitle(isNew ? "Record Dividend" : "Edit Dividend")
            .navigationBarTitleDisplayMode(.inline)
            .background(colorScheme == .dark ? Color(UIColor.systemBackground) : Color(UIColor.secondarySystemBackground))
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(action: {
                        presentationMode.wrappedValue.dismiss()
                    }) {
                        Text("Cancel")
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(action: {
                        if dividend.date > Date.now {
                            showingDateAlert = true
                        } else {
                            stock.saveDividend(dividend: dividend)
                            exchange.updateValues()
                            DataController.shared.saveData()
                            presentationMode.wrappedValue.dismiss()
                        }
                    }) {
                        Text("Save")
                            .bold()
                    }
                }
            }
            .alert(isPresented: $showingDateAlert) {
                Alert(
                    title: Text("Date is in the future"),
                    primaryButton: .default(Text("Save anyway")) {
                        stock.saveDividend(dividend: dividend)
                        DataController.shared.saveData()
                        presentationMode.wrappedValue.dismiss()
                    },
                    secondaryButton: .cancel()
                )
            }
            .alert(isPresented: $showingAlert) {
                Alert(
                    title: Text("Are you sure?"),
                    primaryButton: .destructive(Text("Delete")) {
                        stock.deleteDividend(dividend: dividend)
                    },
                    secondaryButton: .cancel()
                )
            }
        }
    }
}

@Claude31 I have tested using the simulator in iOS 15.2 and in iOS 15.4 and found the following: iOS 15.2 works as expected, values formatted when moving to the next field, accepted, calculated and stored correctly. iOS 15.4 has the issues described above. values not formatting when moving to the next field, not accepted (remain nil), not calculated and not stored.

I wonder if something has changed in the formatter in iOS 15.4? Any help is greatly appreciated

We've discovered this overnight. It's seriously impacting us, issue seems to be having the number be optional. Broken key functionality in our widely used app. Really unnerving a regression like this can happen in a minor iOS release.

I tested the simplest code with format specifier, both with Xcode 13.2.1 / iOS 15.2 simulator and Xcode 13.3 / iOS 15.4 simulator:

struct ContentView: View {
    @State private var value: Double = 20
    var body: some View {
        Text("\(value, specifier: "%.2f")")
    }
}

I get exactly the same result displayed 20.00

So problem is not a change in formatter. But that dividend is not observed properly (or something changed for the observers).

A suggestion, but probably too basic to be the issue. Could you add parenthesis to enclose the result of computation and Double everywhere?

Text("$\( ( Double(dividend.quantity ?? 0) * Double(dividend.value ?? 0) - Double(dividend.fees ?? 0) ), specifier: "%.2f")")

Hi @Claude31

The issue is not with the Text() & specifier it is with the TextField()

TextField("1.234", value: $dividend.value, formatter: decimalFormatter)

where the decimal formatter seems to not work. Changing to

TextField("1.234", value: $dividend.value, format: .number)

seems to have fixed the problem.

I made a sample project which I submitted to Apple Feedback (FB9963196)

import SwiftUI

class Data: ObservableObject {
    @Published var id = UUID().uuidString
    @Published var value1: Double?
    @Published var value2: Int?
}

struct ContentView: View {

    @ObservedObject var data = Data()

    var numberFormatter: NumberFormatter = {
        let nf = NumberFormatter()
        nf.locale = Locale.current
        nf.numberStyle = .decimal
        return nf
    }()

    var decimalFormatter: NumberFormatter = {
        let df = NumberFormatter()
        df.locale = Locale.current
        df.numberStyle = .decimal
        df.generatesDecimalNumbers = true
        return df
    }()

    var body: some View {

        let calc = data.value1 ?? 0 * Double(data.value2 ?? 0)

        Form {
            HStack {
                Text("Value 1")
                TextField("1.234", value: $data.value1, formatter: decimalFormatter)
                    .multilineTextAlignment(.trailing)
                    .keyboardType(.decimalPad)
            }
            HStack {
                Text("Value 2")
                TextField("10", value: $data.value2, formatter: numberFormatter)
                    .multilineTextAlignment(.trailing)
                    .keyboardType(.decimalPad)
            }
            Section {
                Text("Calculated value = \(calc)")
            }
        }
    }
}

if you run this in the simulator in iOS15.2 and 15.4 you will see the issue with the TextField.

As Sam NZ above has indicated that this is due to the value being optional in his project.

TextField does not accept input - TestFlight
 
 
Q