Question: For some reason in the TextField Delegate method shouldChangeCharactersInRange the range.length is always 0...
My Code
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
var shouldChange = true
let newSubjectString = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
let newCharacters = NSCharacterSet(charactersInString: newSubjectString as String)
let currentCharacterCount = textField.text?.utf16.count ?? 0
if (range.length + range.location > currentCharacterCount){
return false
}
if newSubjectString.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) >= 3 {
return false
}
return true
}
I am trying to get rid of the "Undo Bug" (When paste doesn't pass my validation then i try to shake, to Undo, and then the app crashes).. though whenever I check the range.length in this function.. it is always 0. Though this same fix did work in other areas of my app.
To clarify... it is not a crash that I am looking to fix... the fix for the crash is supposed to be the following lines(Which work in other places of my app):
let currentCharacterCount = textField.text?.utf16.count ?? 0
if (range.length + range.location > currentCharacterCount){
return false
}
The issue I am having is that in a specific controller when using the ^ sanity check.. it is not always accurate because range.length is always 0 in this delegate method.
A note on the crashing "undo" bug
As is mentioned in the comments, there is a bug with UITextField that can lead to a crash.
If you paste in to the field, but the paste is prevented by your validation implementation, the paste operation is still recorded in the application's undo buffer. If you then fire an undo (by shaking the device and confirming an Undo), the UITextField will attempt to replace the string it thinks it pasted in to itself with an empty string. This will crash because it never actually pasted the string in to itself. It will try to replace a part of the string that doesn't exist.
Fortunately you can protect the UITextField from killing itself like this. You just need to ensure that the range it proposes to replace does exist within its current string. This is what the initial sanity check above does.
Any help is much appreciated :)