My app used to rely on standard iOS Numpad
Keyboard as a textField.inputView.
The textField
could group typed numbers (1000 -> 1 000, 50067 -> 50 067 etc) and limit the amount of numbers after the decimal point as 2 max: https://i.stack.imgur.com/69LVr.gif (GIF)
I've created a custom numpad keyboard view and implement its logic with UITextInput
protocol according to that guide on StackOverflow.
I can't understand of how to deal with the code I used for grouping and limit numbers with standard iOS Numpad.
Because it doesn't work properly after I type numbers from my new custom Numpad
(only 2 numbers): https://i.stack.imgur.com/f3u3n.gif (GIF)
The code I use for grouping and limit numbers after decimal point in a textField:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.groupingSeparator = " "
formatter.maximumFractionDigits = 2
let textString = textField.text ?? ""
guard let range = Range(range, in: string) else { return false }
let updatedString = textString.replacingCharacters(in: range, with: string)
let correctDecimalString = updatedString.replacingOccurrences(of: ",", with: ".")
let completeString = correctDecimalString.replacingOccurrences(of: formatter.groupingSeparator, with: "")
guard completeString.count <= 12 else { return false }
guard !completeString.isEmpty else { return true }
textField.text = completeString
return string == formatter.decimalSeparator
}
- Custom
NumpadView:
class NumpadView: UIView {
var target: UITextInput?
init(target: UITextInput) {
super.init(frame: .zero)
self.target = target
initializeSubview()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
initializeSubview()
}
func initializeSubview() {
let xibFileName = "NumpadView"
let view = Bundle.main.loadNibNamed(xibFileName, owner: self, options: nil)![0] as! UIView
self.addSubview(view)
view.frame = self.bounds
self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
@IBAction func buttonPressed(_ sender: NumpadButton) {
insertText((sender.titleLabel!.text)!)
}
func insertText(_ string: String) {
guard let range = target?.selectedRange else { return }
if let textField = target as? UITextField, textField.delegate?.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) == false {
return
}
target?.insertText(string)
}
}
extension UITextInput {
var selectedRange: NSRange? {
guard let selectedRange = selectedTextRange else { return nil }
let location = offset(from: beginningOfDocument, to: selectedRange.start)
let length = offset(from: selectedRange.start, to: selectedRange.end)
return NSRange(location: location, length: length)
}
}
2.How I initialize it in a VC:
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
textField.inputView = NumpadView(target: textField)
}
Test project on GitHub: CLICK
What should I do so the code in shouldChangeCharactersIn
method work for my custom Numpad?