StateObject 变量上的 SwiftUI isEmpty 总是 returns true
SwiftUI isEmpty on StateObject variable always returns true
我正在尝试进行表单验证,检查 TextField 的值是否为空以禁用该表单上的保存按钮。
然而,即使在 TextField 中输入了值,“isEmpty”的检查似乎总是 returns true。
所以该按钮始终处于禁用状态。
这是我的表单的样子:
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)
}
}
}
}
这是使用的视图模型:
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()
}
}
}
这是 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)
}
}
}
这里的问题是您的 standingHeight
变量属于 String
类型。将该实现更改为 Int
就可以了。
@Published var standingHeight: Int = 0
在您看来:
.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)
}
}
}
编辑:
NumberFormatter
和 String
var 的组合是这不起作用的原因。 NumberFormatter
尝试将数字放入 String
变量中。这应该会引发错误,但它似乎会优雅地结束。您的 standingHeight
var 始终保持 ""
,因此 .isEmpty
始终为真且永远不会改变。
我正在尝试进行表单验证,检查 TextField 的值是否为空以禁用该表单上的保存按钮。 然而,即使在 TextField 中输入了值,“isEmpty”的检查似乎总是 returns true。 所以该按钮始终处于禁用状态。
这是我的表单的样子:
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)
}
}
}
}
这是使用的视图模型:
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()
}
}
}
这是 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)
}
}
}
这里的问题是您的 standingHeight
变量属于 String
类型。将该实现更改为 Int
就可以了。
@Published var standingHeight: Int = 0
在您看来:
.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)
}
}
}
编辑:
NumberFormatter
和 String
var 的组合是这不起作用的原因。 NumberFormatter
尝试将数字放入 String
变量中。这应该会引发错误,但它似乎会优雅地结束。您的 standingHeight
var 始终保持 ""
,因此 .isEmpty
始终为真且永远不会改变。