3

I have one textfield, & use shouldChangeCharactersInRange method to get value.

Here is my Code:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{

    NSLog(@"Pressing : %@\n", string);
    NSMutableString *text = [NSMutableString stringWithString:textField.text];

    NSLog(@"length: %lu", (unsigned long)range.length);
    NSLog(@"location: %lu\n", (unsigned long)range.location);
    NSLog(@"before text: %@", textField.text);

    [text replaceCharactersInRange:range withString:string];
    NSLog(@"After replacement , Text: %@\n\n", text);

    // My work..

    return YES;
}

I first add character 'T' to textfield, it works fine ..

2016-03-02 10:06:23.162 MyTextFieldApp[12006:4323645] Pressing : T
2016-03-02 10:06:23.163 MyTextFieldApp[12006:4323645] length: 0
2016-03-02 10:06:23.163 MyTextFieldApp[12006:4323645] location: 0
2016-03-02 10:06:23.163 MyTextFieldApp[12006:4323645] before text: 
2016-03-02 10:06:23.163 MyTextFieldApp[12006:4323645] After replacement , Text: T

Then, I backspace it to remove character, that also works fine..

2016-03-02 10:06:30.979 MyTextFieldApp[12006:4323645] Pressing : 
2016-03-02 10:06:30.980 MyTextFieldApp[12006:4323645] length: 1
2016-03-02 10:06:30.980 MyTextFieldApp[12006:4323645] location: 0
2016-03-02 10:06:30.980 MyTextFieldApp[12006:4323645] before text: T
2016-03-02 10:06:30.981 MyTextFieldApp[12006:4323645] After replacement , Text: 

But, when I am going to add new character then, it crash on replaceString..

Note: This time, Range Gives length 0 & location 1, while first time also when i am adding T to empty textfield, it gives length 0 as well as location 0.

2016-03-02 10:07:02.158 MyTextFieldApp[12006:4323645] Pressing : T
2016-03-02 10:07:02.158 MyTextFieldApp[12006:4323645] length: 0
2016-03-02 10:07:02.159 MyTextFieldApp[12006:4323645] location: 1
2016-03-02 10:07:02.159 MyTextFieldApp[12006:4323645] before text: 
2016-03-02 10:07:02.159 MyTextFieldApp[12006:4323645] *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFString replaceCharactersInRange:withString:]: Range or index out of bounds'

I can't detect where is the problem?

Sneha
  • 880
  • 9
  • 24

1 Answers1

5

Your program is crashing because you are attempting to insert data at an invalid location in the text mutable string.

The second time you press 'T', the value of text (retrieved from textField.text) is an empty string (literally @""). You then call replaceCharactersInRange passing a location of 1 and length 0. When you call replaceCharactersInRange with a length of 0 you are effectively saying "insert string" at position location. This function only replaces text when the length is greater than 0.

When your code tries to insert the letter 'T' at the index 1 it can't (the first and only valid index of an empty string is 0), so the program crashes.

Also, for what it's worth, your program shouldn't return a location of 1 and a length of 0 if the textField is empty. There must be something else going on. I wrote your sample program in Swift and got the following output:

import UIKit

class ViewController: UIViewController {
    var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor.blackColor()

        textField = UITextField(frame: CGRectMake(20, 100, 200, 20))
        textField.backgroundColor = UIColor.whiteColor()
        textField.delegate = self

        view.addSubview(textField)
    }
}


extension ViewController: UITextFieldDelegate {
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        print("range.length: \(range.length), range.location: \(range.location), text: '\(textField.text!)' string: '\(string)'")
        return true
    }
}

output:

range.length: 0, range.location: 0, text: '' string: 'T' // press T
range.length: 1, range.location: 0, text: 'T' string: '' // press backspace
range.length: 0, range.location: 0, text: '' string: 'T' // press T

As you can see, I see the expected range of 0,0 on the second insert of T. An Objective-C program should behave similarly.

par
  • 17,361
  • 4
  • 65
  • 80
  • I don't know, something is wrong with your program or something else was typed in the field. I wrote the exact same program just to sanity check that UITextField is doing the right thing and as you can see from my output the ranges I get are fine. – par Mar 02 '16 at 05:57