'SwiftUI isEmpty on StateObject variable always returns true
I'm trying to get a form validation that checks if the value of a TextField isEmpty to disable the save button on that form. However it seems the check for "isEmpty" always returns true even when a value is entered in the TextField. So the button always stays disabled.
This is what my form looks like:
struct AddPHVTestView: View {
@StateObject private var addPHVTestVM = AddPHVTestViewModel()
@Environment(\.presentationMode) var presentationMode
let player: PlayerViewModel
/*private var formIsValid : Bool {
return (addPHVTestVM.standingHeight.isEmpty /* || addPHVTestVM.sittingHeight = "" || addPHVTestVM.chairHeight = "" || addPHVTestVM.weight = ""*/)
}*/
private var disableForm: Bool {
addPHVTestVM.standingHeight.isEmpty
}
var body: some View {
VStack(alignment: .leading) {
Text("Test für \(player.firstName)")
.font(.title)
.padding(.horizontal)
.padding(.top)
Form {
FormDatePickerCellView(date: $addPHVTestVM.testdate, label: "Testdatum", image: "calendar")
FormTextFieldNumberCellView(text: $addPHVTestVM.standingHeight, label: "Größe im Stand", image: "figure.wave", placeholder: "in cm")
.keyboardType(.decimalPad)
HStack {
Spacer()
Button {
print(disableForm)
//addPHVTestVM.addPHVTestForPlayer(vm: player)
presentationMode.wrappedValue.dismiss()
} label: {
Text("Speichern")
}
.disabled(disableForm)
Spacer()
}
}
.padding(.top, -20)
.onChange(of: addPHVTestVM.standingHeight) { newValue in
//print(formIsValid)
}
}
}
}
This is the viewModel used:
class AddPHVTestViewModel: ObservableObject {
@Published var testdate: Date = Date()
@Published var standingHeight: String = ""
@Published var sittingHeight: String = ""
@Published var weight: String = ""
@Published var chairHeight: String = ""
func addPHVTestForPlayer(vm: PlayerViewModel) {
let player: Player? = Player.byId(id: vm.id)
if let player = player {
let phvTest = PHVTest(context: PHVTest.viewContext)
phvTest.testDate = testdate
phvTest.standingHeight = Double(standingHeight) ?? 0.0
phvTest.sittingHeight = Double(sittingHeight) ?? 0.0
phvTest.weight = Double(weight) ?? 0.0
phvTest.chairHeight = Double(chairHeight) ?? 0.0
phvTest.player = player
phvTest.save()
}
}
}
And here is the FormTextFieldNumberCellView:
struct FormTextFieldNumberCellView: View {
@Binding var text: String
let label: String
let image: String
let placeholder: String
let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}()
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Label("\(label)", systemImage: "\(image)")
.font(.footnote)
TextField("\(placeholder)", value: $text, formatter: formatter)
.frame(maxWidth: .infinity)
.padding(.top, 5)
}
}
}
Solution 1:[1]
The issue here is your standingHeight
var being of type String
. Change that implementation to be an Int
and you are good to go.
@Published var standingHeight: Int = 0
and in your View:
.disabled(addPHVTestVM.standingHeight == 0)
struct FormTextFieldNumberCellView: View {
@Binding var text: Int
let label: String
let image: String
let placeholder: String
let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}()
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Label("\(label)", systemImage: "\(image)")
.font(.footnote)
TextField("\(placeholder)", value: $text, formatter: formatter)
.keyboardType(.decimalPad)
.frame(maxWidth: .infinity)
.padding(.top, 5)
}
}
}
Edit:
The combination of NumberFormatter
and the String
var is the reason this is not working. The NumberFormatter
tries to put a number in a String
var. This should throw an error but it seems it dies gracefully. Your standingHeight
var allways stays ""
, so .isEmpty
is allways true and it never changes.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |