【问题标题】:SwiftUI - How do you set a maximum number on a TextField?SwiftUI - 如何在 TextField 上设置最大数量?
【发布时间】:2020-05-27 04:02:48
【问题描述】:

对于我的应用,我需要用户输入一个介于 1 到 1000 之间的数字,并且我想验证它是否在这些数字之间。起初我想使用Stepper,但随后用户将不得不按+ 一千次。有一个更好的方法吗?我这样做是为了提示用户numberPad,但允许用户输入任何数字。

这是我的代码:

@State var validityPeriod = ""

var body: some View {
    NavigationView {
        Form {
            TextField("Validity Period (In Days)", text: $validityPeriod)
        }
        .navigationBarTitle("Validation")
    }
}

我可以在提交表单之前检查他们输入的数字,但我更喜欢在他们输入时验证字段的东西。

注意:我将 Xcode 11.5 与 Swift 5 一起使用

【问题讨论】:

  • 这能回答你的问题吗? swift - validating UITextField
  • @Chris 您的链接谈到了 Swift 的 UITextField,而我正在尝试使用 SwiftUI 的 TextField
  • 对不起,你是对的!
  • 嘿,我在回答中添加了不同的方法。您可以使用didSet 来限制甚至可以在TextField 中输入的文本。很整洁。

标签: swift swiftui textfield


【解决方案1】:

您可以通过计算的 Bool 属性检查当前值是否有效。然后,您可以在任何您想要的地方将该检查放入您的代码中。

每次您的@State 变量更改时,SwiftUI 都会重新创建 ContentView body(最好将其设为私有,仅供参考)。它在仅重新渲染所需内容方面具有一定的智能,但基本上您的整个视图都会重新评估,并且每次击键都会重新测试您计算出的 bool periodIsValid。

当表单无效时,提交按钮经常被禁用。比如:

Button(...) {
    ...
}
.disabled(!periodIsValid)

要进行实时验证,您可以通过实时验证检查来做许多创造性的事情。真正简单的方法是让输入的文本在无效时变为红色:

struct ContentView: View {
    @State private var validityPeriod = ""

    var periodIsValid: Bool {
        guard let days = Int(validityPeriod) else { return false}
        guard days >= 1 && days <= 1000 else { return false }
        return true
    }

    var body: some View {
        NavigationView {
            Form {
                TextField("Validity Period (In Days)", text: $validityPeriod)
                    .foregroundColor(periodIsValid ? .primary : .red)
            }
            .navigationBarTitle("Validation")
        }
    }
}

编辑:

您还可以限制条目值...

仔细想想,您实际上可以对文本字段执行即时验证,这将防止输入无效文本。

为此,您使用didSet 属性包装器。唯一的问题是它不适用于@State 包装器,因此您必须改用@ObservedObject。很简单...

请注意,您可能希望帮助人们了解正在发生的事情。如果您的界面还没有明确说明哪些值是可以的,您可能需要在压缩无效条目时提供提示。

class ValidityPeriod: ObservableObject {
    @Published var validityPeriod = "" {
        didSet {
            // Allow blanks in the field, or they can't delete
            if validityPeriod == "" { return }

            // Check the entire value is good, otherwise ignore the change
            let days = Int(validityPeriod) ?? 0
            if days < 1 || days > 1000 { validityPeriod = oldValue }

            // Pop alert or trigger any other UI instruction here
        }
    }
}

struct ContentView: View {

    @ObservedObject var vp = ValidityPeriod()

    var body: some View {
        NavigationView {
            Form {
                TextField("Validity Period (In Days)", text: $vp.validityPeriod)
            }
            .navigationBarTitle("Validation")
        }
    }
}

【讨论】:

  • var isValidPeriod: Bool { 1...1000 ~= Int(validityPeriod) ?? 0 }
  • 如果文本无效,将文本变为红色是个好主意。我将您的代码与我在这里找到的 stackoverflow.com/a/58736068/7487335 结合起来,这让我可以完全屏蔽字母。谢谢!
  • 嘿。我们同时打字。您发布的方法和didSet 方法都可以正常工作。
猜你喜欢
  • 2019-10-21
  • 2018-05-27
  • 2020-09-30
  • 2022-01-04
  • 2019-10-24
  • 2020-03-09
  • 2019-11-22
  • 2011-04-20
  • 1970-01-01
相关资源
最近更新 更多