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)
