微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SwiftUI:TextField 条件验证

如何解决SwiftUI:TextField 条件验证

用户可以使用 TextFields 提供一些数字输入。如果选择器设置为“绘图”,则任何有效数字都可以,但如果设置为“映射”,则验证必须将数字限制在(在这种情况下)-180 和 +180 之间。好的数字显示绿色轮廓,坏数字显示红色。

在更改选择器之前,我可以很好地处理验证。例如1234 的输入对于“绘图”很好,但切换到“地图”仍然显示绿色,如果不是。 The same is true when an invalid "map" number (showing red) remains invalid when the picker is changed to "plot".无论是否关注该特定 TextField,都是如此。

我已将其缩减为下面演示问题的少量代码。我不确定我的逻辑是错误的还是我没有正确实现它。任何帮助表示赞赏。

enter image description here

struct ContentView: View {

   @StateObject var addPatternVM = AddPatternVM()

   var body: some View {
       vstack {
           Picker(selection: $addPatternVM.type,label: Text("")) {
               Text("Plot").tag("plot")
               Text("Map").tag("map")
           }.pickerStyle(SegmentedPickerStyle())
           TextField(addPatternVM.type == "plot" ? "Minimum x" : "Minimum longitude",text: $addPatternVM.minimumXString)
               .textFieldStyle(BorderedTextView(isGood: addPatternVM.minimumXIsGood))
               .onChange(of: addPatternVM.minimumXString) { newValue in
                   addPatternVM.isMinimumXGood(newValue: newValue)
               }
       }.padding()
   }
}

我的简化视图模型:

class AddPatternVM: ObservableObject {

   @Published var type: String = "plot"
   @Published var minimumXIsGood = false
   @Published var minimumXString = ""

   func isMinimumXGood(newValue: String) {
       if type == "plot" {
           if numberIsGood(newValue: newValue) {
               minimumXIsGood = true
           } else {
               minimumXIsGood = false
           }
       } else if type == "map" {
           if longitudeIsGood(newValue: newValue) {
               minimumXIsGood = true
           } else {
               minimumXIsGood = false
           }
       }
   }

   func numberIsGood(newValue: String) -> Bool {
       return Double(newValue) != nil ? true : false
   }

   func longitudeIsGood(newValue: String) -> Bool {
       guard let longitude = Double(newValue) else { return false }
    
       if longitude < -180.0 || longitude > 180.0 {
           return false
       } else {
           return true
       }
   }
}

这只是我用来显示有效/无效输入的 TextFieldStyle。

struct BorderedTextView: TextFieldStyle {

   var isGood: Bool

   public func _body(
       configuration: TextField<Self._Label>) -> some View {
       return configuration
           .padding(EdgeInsets(top: 8,leading: 16,bottom: 8,trailing: 16))
           .background(Color.white)
           .overlay(RoundedRectangle(cornerRadius: 8)
                       .stroke(linewidth: 1)
                       .foregroundColor(isGood ? .green : .red))
   }
}

解决方法

我所看到的问题是,当您将选择器从绘图更改为地图时,您不会重新计算“minimumXIsGood”值,反之亦然。试试这个:

    Picker(selection: $addPatternVM.type,label: Text("")) {
        Text("Plot").tag("plot")
        Text("Map").tag("map")
    }.pickerStyle(SegmentedPickerStyle())
    .onChange(of: addPatternVM.type) { _ in
        addPatternVM.isMinimumXGood(newValue: addPatternVM.minimumXString)
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。