Dante
Dante

Reputation: 27

How to automatically advance cursor to next field when user types a certain number of characters

I have a sign up page for my app. Users are prompted to enter a cell number and a four digit PIN for use in the app. There are three cell fields to help with standardization of the cell format--the first field is three digits and holds the area code, the second field is also three digits, and the last field is four. The PIN field comes next. I want the next field to become active when the user enters the correct number of digits in a given box. For example, when someone types in three digits of the area code, the cursor should progress to the next box.

I've gotten it to work so that if one continues typing the cursor will move. However, it only moves after the next digit is typed (for example, you type three digits of the area code, then type another digit, and that digit will appear in the next box along with the cursor; the cursor does not move after typing only three digits). Additionally, the method I am using appears to have a glitch that makes it impossible to edit the fields if they already have the desired number of characters.

This is the code I am using currently:

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

    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSUInteger newLength = newString.length;

    if (textField.tag == 3) {
        if (newLength == 4) {
            [cellField2 becomeFirstResponder];
        }
    }
        if (textField.tag == 4) {
            if (newLength == 4) {
                [cellField3 becomeFirstResponder];
            }
        }
            if (textField.tag == 5) {
                if (newLength == 5) {
                    [pinField becomeFirstResponder];
                }
        }
    if (textField.tag == 6) {
        if (newLength == 5) {
            [pinField resignFirstResponder];
        }
    }

    return YES;
}

I appreciate any help, thanks.

ETA: edited to include danh's code, which I know is more correct than what I was doing. However, my cursor problem remains.

Upvotes: 1

Views: 2709

Answers (3)

woogii
woogii

Reputation: 413

lnafziger's answer works great! Those who are finding a swift solution, here is my swift 2.2 code.

func textField(textField: UITextField, shouldChangeCharactersInRangerange: NSRange, replacementString string: String)-> Bool 
{

    let newString = ((textField.text)! as NSString).stringByReplacingCharactersInRange(range, withString: string)// Convert text into NSString in order to use 'stringByReplacingCharactersInRange' function

    let newLength = newString.characters.count  // Count the length of 'String' type variable

    if (textField == cellField1) {

        if (newLength == 3) {

            cellField1.text = newString
            cellField2.becomeFirstResponder()
            return false
        }
    }

    if (textField == cellField2) {

        if (newLength == 3) {

            cellField2.text = newString
            cellField3.becomeFirstResponder()
            return false
        }
    }

    if (textField == cellField3) {

        if (newLength == 4) {

            cellField3.text = newString
            pinField.becomeFirstResponder()
            return false
        }
    }

    if (textField == pinField) {

        if (newLength == 5) {

            pinField.resignFirstResponder()
            return true
        }
    }

    return true

}

Upvotes: 0

lnafziger
lnafziger

Reputation: 25740

Note that you don't need to use tag's since you have them all in outlets so you could just use: if (textField == cellField1) {, or even better: if (textField == self.cellField1) {. This also makes it easier to follow your code and identify which textField that you are operating on.

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

    NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSUInteger newLength = newString.length;

    if (textField == self.cellField1) {
        if (newLength == 3) {
            [cellField1 setText:newString];
            [cellField2 becomeFirstResponder];
            return NO; // NO because we already updated the text.
        }
    }

    if (textField == self.cellField2) {
        if (newLength == 3) {
            [cellField2 setText:newString];
            [cellField3 becomeFirstResponder];
            return NO;
        }
    }

    if (textField == self.cellField3) {
        if (newLength == 4) {
            [cellField3 setText:newString];
            [pinField becomeFirstResponder];
            return NO;
        }
    }

    if (textField == pinField) {
        if (newLength == 5) {
            [pinField resignFirstResponder];
            return YES;
        }
    }

    return YES;
}

Upvotes: 2

danh
danh

Reputation: 62686

A few things:

newLength needs first to have the the new string, this should solve the counting problem:

NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
NSUInteger newLength = newString.length;

Next, you can just send becomeFirstResponder. No need to send resign since it's implicit in the become.

And this method should answer YES at the end.

Upvotes: 1

Related Questions