1

I have 10 textfields, each of which could hold at most one character. When I enter a character in the first textfield, the focus should automatically move to the next textfield and so on. That is, as soon as the first character is entered in a textfield, the focus should shift to the next. That is, the next textfield should become the first responder. I have written the below code, used the textfield delegate method.

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

NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"];

for (int i = 0; i < [string length]; i++) {
    unichar c = [string characterAtIndex:i];
    if([myCharSet characterIsMember:c])
    {
        int previousTag = textField.tag;


        if([textField.text length] > 0)
        {
            if((previousTag == 9) && ([textField10.text length] >0))
            {
                return NO;
            }
            UITextField *tempField=(UITextField *)[self.view viewWithTag:previousTag+1]; 
            if([tempField.text length] > 0){
                [tempField resignFirstResponder];
                return NO;
            }
            [tempField becomeFirstResponder];
            return YES;
        }

    }
    else{
        return NO;
    }
}


return YES;
}

But I am not getting the desired results. When I type a character its entered in the first textfield, but the focus is not shifting to the next, though when I type the 2nd character, it is entered in the next textfield.

Similarly, I need to write a delete function such that when I delete a textfield, the focus automatically shifts to the previous textfield.

Any answers will be appreciated. Thanks.

Xavi Valero
  • 2,047
  • 7
  • 42
  • 80

2 Answers2

2

-shouldChangeCharactersInRange gets called before text field actually changes its text. So you will be getting the old value in the string. Add the line at the beginning of your method. It should fix your problem.

string = [textField.text stringByReplacingCharactersInRange:range withString:string];
sElanthiraiyan
  • 6,000
  • 1
  • 31
  • 38
  • Didn't get you. Could you please explain. As u said, I have added the above code to mine. But still not getting right – Xavi Valero Dec 05 '11 at 14:23
  • The thing is that in the moment of checking ` if([textField.text length] > 0)` textField.text contains the old value, the changes in STRING are not applied yet. So if the field is empty and you write sth this will return NO, but when you type again, there is already sth so the condition is satisfied. Note: name of this method is SHOULD so you are telling the system whether to change value or not – Michał Zygar Dec 05 '11 at 14:34
  • Whats the best way to go about this. I am still confused. – Xavi Valero Dec 05 '11 at 14:42
  • The problem is that, while using this delegate method, if I set the next textfield as first responder, before the method returns YES, then the value I am trying to enter in the first textfield, gets entered in the next.I just cant find another way to solve this problem – Xavi Valero Dec 05 '11 at 14:58
2

You can always return NO and change the textField text manually. I guess what you need is something like this.

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

NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"];
int previousTag = textField.tag;

if ([string isEqualToString:@""]) {//backspace button
    if (previousTag==0) {//added to prevent crashing in first tf
        return YES;
    }
  UITextField *tempField2=(UITextField *)[self.view viewWithTag:previousTag-1]; 

    textField.text=string;
    [tempField2 becomeFirstResponder];
    return NO;

}
for (int i = 0; i < [string length]; i++) {
    unichar c = [string characterAtIndex:i];
    if([myCharSet characterIsMember:c])
    {
        if((previousTag == 9) && ([textField10.text length] >0))
        {
            return NO;
        }

        UITextField *tempField=(UITextField *)[self.view viewWithTag:previousTag+1]; 
        if([tempField.text length] > 0)
        { 
            textField.text=string;
            [tempField resignFirstResponder];
            return NO;
        }
        textField.text=string;
        [tempField becomeFirstResponder];
        return NO;

    }
    else{
        return NO;
    }


}


return YES;
}
Michał Zygar
  • 4,052
  • 1
  • 23
  • 36