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)
        }
    }
}

编辑:

NumberFormatterString var 的组合是这不起作用的原因。 NumberFormatter 尝试将数字放入 String 变量中。这应该会引发错误,但它似乎会优雅地结束。您的 standingHeight var 始终保持 "",因此 .isEmpty 始终为真且永远不会改变。