AnyFormatKit
AnyFormatKit copied to clipboard
Filtering entered/pasted characters
Users can input any characters either by using a physical keyboard, or copy pasting into FormatTextField
.
The issue is most prominent when the user is trying to paste something. Here is our example:
private struct AccountEditorView: View {
@Binding var text: String
let prompt: String
let textColor: Color
let cursorColor: Color
var body: some View {
FormatTextField(
unformattedText: $text,
placeholder: prompt,
textPattern: "######## - ######## - ########"
)
.font(.body1)
.keyboardType(.numberPad)
.foregroundColor(textColor)
.accentColor(cursorColor)
}
}
user pastes: 12345678 - 12345678 - 12345678
FormatTextField shows: 12345678 - 12345678 - 12
Despite Tinamu's suggestion on a previous issue, this problem cannot be solved on SwiftUI view level, nor with using .onReceive
modifier, nor with using a custom Binding
implementation that filters the input, because these filtering closures run after the paste happened.
Suggested solution
FormatTextField
should accept an optional CharacterSet
as an init argument.
If given, use this characterset to filter user input at the very first line of
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
The following proof of concept solution seems to fix the problem:
private let allowedInput: CharacterSet = .decimalDigits
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let string = String(string.unicodeScalars.filter { self.allowedInput.contains($0) })