SwiftUI - 如何在 TextField 上设置最大数量?

Posted

技术标签:

【中文标题】SwiftUI - 如何在 TextField 上设置最大数量?【英文标题】:SwiftUI - How do you set a maximum number on a 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 中输入的文本。很整洁。 【参考方案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 如果文本无效,将文本变为红色是个好主意。我将您的代码与我在这里找到的 ***.com/a/58736068/7487335 结合起来,这让我可以完全屏蔽字母。谢谢! 嘿。我们同时打字。您发布的方法和didSet 方法都可以正常工作。

以上是关于SwiftUI - 如何在 TextField 上设置最大数量?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 TextField 在 SwiftUI 列表中消失?

如何在 SwiftUI 中检测 TextField 的实时变化?

SwiftUI 上带有 TextField 的可删除表

SwiftUI 上带有 TextField 的可删除表

如何在按钮单击时在 SwiftUI 中为 TextField 设置文本

我如何在SWIFTUI中把textField作为firstResponder,就像Swift一样:textField.becomesFirstResponder。