-
Notifications
You must be signed in to change notification settings - Fork 57
Description
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) })