简体   繁体   English

使用 SwiftUI 将 TextField 限制为 x 个字符

[英]Limit TextField to x amount of characters using SwiftUI

Using iOS13.2, Swift-5.1.2, Xcode-11.2, I try the following:使用 iOS13.2、Swift-5.1.2、Xcode-11.2,我尝试以下操作:

I want to use a TextField.我想使用一个文本字段。 The user shall only be able to enter x-amount of characters into the TextField.用户只能在 TextField 中输入 x 个字符。

My code looks as follows:我的代码如下所示:

import Combine
import SwiftUI

class Entry: ObservableObject {

  @Published var entry = "" {
    didSet {
        entry = String(entry.prefix(6)) // trying to limit to 6 characters
    }
  }
}

And in the above code, there is already the exception line.而在上面的代码中,已经有异常行了。

I can see that the didSet{...} is wrong (since we end up in an endless loop setting/didSetting again and again)...我可以看到didSet{...}是错误的(因为我们最终陷入无限循环设置/didSetting 一次又一次)...

What is a better way to limit a TextField to x-amount of characters?将 TextField 限制为 x 个字符的更好方法是什么?

Here is the rest of the code:这是代码的rest:

struct NumberView: View {
    var body: some View {

        Group {
            HStack {
                Spacer()
                NumberIcon(number: 1)
                NumberIcon(number: 2)
                NumberIcon(number: 3)
                NumberIcon(number: 4)
                NumberIcon(number: 5)
                NumberIcon(number: 6)
                Spacer()
            }
         }
    }
}
struct NumberIcon: View {
    @ObservedObject private var entry = Entry()
    var number: Int = 0
    var body: some View {
        TextField(" ", text: $entry.entry, onEditingChanged: { editing in
            print(editing)
            print(self.$entry)
        })
            .padding()
            .foregroundColor(Color.black)
            .background(Color.green)
            .font(.largeTitle)
            .lineLimit(1)
            .cornerRadius(16.0)
            .clipped()
            .keyboardType(.numberPad)
    }
}

struct NumberView_Previews: PreviewProvider {
    static var previews: some View {
        NumberView()
    }
}

I know that there are UIKit wrapper possibilities to use the good-old shouldChangeCharactersIn delegate methods form UITextFieldDelegate - but I would like to implement the character limitation purely with SwiftUI (no UIKit code).我知道有 UIKit 包装器可能使用 UITextFieldDelegate 形式的旧shouldChangeCharactersIn委托方法 - 但我想纯粹使用 SwiftUI (没有 Z9CFED124ECBE655AF2584273379C 代码)来实现字符限制。 How can I do that?我怎样才能做到这一点?

Thanks to this answer here , I found a solution:多亏了这里的答案,我找到了解决方案:

The Entry class can be rewritten:条目 class 可以重写:

class Entry: ObservableObject {

    let characterLimit = 6   // limiting to 6 characters
    @Published var entry = "" {
        didSet {
            if entry.count > characterLimit && oldValue.count <= characterLimit {
                entry = oldValue
            }
        }
    }
}

The easiest way to achive this in SwiftUI is just to disable the TextField when the maximum number of characters is reached:在 SwiftUI 中实现这一目标的最简单方法是在达到最大字符数时禁用 TextField:

struct LimittedTextField: View {

    @State private var entry = ""

    let characterLimit = 6

    var body: some View {
        TextField("", text: $entry)
            .disabled(entry.count > (characterLimit - 1))
    }
}

I've written a library for these kinds of use cases:我为这些用例编写了一个

import DataField

struct ContentView: View {

    @State private var text = ""
    private let characterLimit = 6

    var body: some View {
        DataField("My Field", data: $text) { text in text.count < 6 } 
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM