0

How could you get a TextField to only append to the text variable when the input is not already present?

So if you had already typed "abc" and you tried to type 'a' again, it wouldn't do anything

Starting point:

TextField("list of characters", text: $characterSequence)
   .onReceive{

   }

1 Answers1

3

You can check strings like this and input only a new char.

Note: This code is a case-sensitive input string.

TextField("list of characters", text: $characterSequence)
    .onReceive(Just(characterSequence), perform: { char in
        print(char)
        let oldString = characterSequence.dropLast()
        if let last = characterSequence.last, oldString.contains(last) {
            characterSequence = String(characterSequence.dropLast())
        }
    })

For, without a case-sensitive input string.

TextField("list of characters", text: $characterSequence)
    .onReceive(Just(characterSequence), perform: { char in
        print(char)
        let oldString = characterSequence.dropLast()
        if let last = characterSequence.last, oldString.uppercased().contains(last.uppercased()) {
        characterSequence = String(characterSequence.dropLast())
    }
})

Edit

For the disabled characters in the middle, use UITextField with UIViewRepresentable. This one is also handled copy-past to the text field.

Here is solution

struct UniqueTextField: UIViewRepresentable {
    private var placeholder: String?
    
    @Binding private var text: String
    
    init(_ placeholder: String? = nil, text: Binding<String>) {
        _text = text
        self.placeholder = placeholder
    }
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.placeholder = placeholder
        textField.text = text
        textField.delegate = context.coordinator
        return textField
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator()
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            /**
             // case-sensitive
             string.filter({(textField.text ?? "").contains($0)}).isEmpty
             */
            //without case-sensitive
            string.filter({(textField.text?.uppercased() ?? "").contains($0.uppercased())}).isEmpty
        }
    }
}

Usage:

UniqueTextField("list of characters", text: $characterSequence)

enter image description here

Raja Kishan
  • 16,767
  • 2
  • 26
  • 52