0

My class is registered as the text field delegate, and part of its function includes implementing textField:shouldChangeCharactersInRange:replacementString like this:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    self.stateHolder.fieldValue = [self.stateHolder.fieldValue stringByReplacingCharactersInRange:range withString:string];

    return YES;
}

I started noticing a crash when entering diacritics from the hardware keyboard into an empty text field. Here's the error I'm seeing:

Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFString replaceCharactersInRange:withString:]: Range or index out of bounds'

It appears that when entering the diacritic from a hardware keyboard, the range that is associated with entering it is "location=1, length=0". This is what's causing an index out of bounds exception when trying to save it in the string. Does anyone know of a way around this crash?

kb920
  • 3,039
  • 2
  • 33
  • 44
Chris
  • 909
  • 8
  • 18

1 Answers1

0

the fieldValue length should be greater than or equal to the replacement string length, else there wont be enough range to replace the characters.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
       if(self.stateHolder.fieldValue.length>=string.length){
    self.stateHolder.fieldValue = [self.stateHolder.fieldValue stringByReplacingCharactersInRange:range withString:string];
     }

    return YES;
}

For example:

          fieldValue= @"Hello";   length=5
           replacementString=@"'"; length=1     1 can be replaced in 5

              fieldValue= @"";   length=0    length 0 or nil,
           replacementString=@"'"; length=1 , but not 1 can be replaced in 0
Teja Nandamuri
  • 11,045
  • 6
  • 57
  • 109
  • While that does resolve the initial issue, I think it may have opened pandora's box. I'm able to enter the diacritic, but then backspacing on it causes the same type of error. It appears that condition you added circumvented the problem by simply not adding the character to the "fieldValue" string, so backspacing caused it to replace a range on an empty string. – Chris Apr 21 '16 at 17:36
  • you could detect the backspace and ignore it.For detecting backspace: http://stackoverflow.com/questions/25371254/how-to-detect-delete-key-on-an-uitextfield-in-ios-8 – Teja Nandamuri Apr 21 '16 at 17:37
  • Actually if you first enter a symbol, and then press backspace(delete) key, it shouldn't lead to crash, as you are trying to replace nothing. – Teja Nandamuri Apr 21 '16 at 17:40
  • Can you provide the inputs you providing that lead to crash ?@Chris – Teja Nandamuri Apr 21 '16 at 17:41
  • From the mac's keyboard, type alt+n, then n again when the text field is empty. With my code, it'll immediately crash. With your modifications, I'll successfully see the ñ in the text field, but then it will crash when you press backspace. – Chris Apr 21 '16 at 17:45
  • what is the value of fieldValue at the beginning? – Teja Nandamuri Apr 21 '16 at 17:49
  • Nothing, It's empty. – Chris Apr 21 '16 at 17:50
  • That's the problem, you should not have that empty , atleast you should give it a value with a space character @" " – Teja Nandamuri Apr 21 '16 at 17:53
  • try giving fieldValue=@" "; in viewDidLoad there is a space character in between the double quotes. – Teja Nandamuri Apr 21 '16 at 17:53
  • I'm starting to think it's not worth trying to code for this scenario. This only seems to happen when using the mac's keyboard, never the simulator's soft one. I'll test it on a physical device and see if I run into this issue. – Chris Apr 21 '16 at 17:54
  • Yeah you are right too, just in case if in future there is a key in the iphone keyboard, you could follow this approach. – Teja Nandamuri Apr 21 '16 at 17:55