Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 6 UITextField Secure - How to detect backspace clearing all characters?

In iOS 6 if you type text into a secure text field, change to another text field, then come back to the secure text field and hit backspace, all of the characters are removed. I am fine with this happening, however, I am trying to enable/disable a button based on if this secure text field has characters in it or not. I know how to determine what characters are in the fields and if a backspace is hit but I am having trouble determining how to detect if clearing of all the characters is happening.

This is the delegate method I'm using to get the new text of a field, but, I can't seem to figure out how to get the new text (assuming the new text would just be a blank string) if a backspace is hit that clears all the characters.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    //returns the "new text" of the field
    NSString * text = [textField.text stringByReplacingCharactersInRange:range withString:string];
}

Any help is much appreciated.

Thanks!

like image 760
crizzwald Avatar asked May 27 '13 01:05

crizzwald


2 Answers

I use this solution. It does not need local variables and sets the cursor position correctly, after deleting the char.

It's a mashup of this solutions:

  • Backspace functionality in iOS 6 & iOS 5 for UITextfield with 'secure' attribute
  • how to move cursor in UITextField after setting its value

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        if (range.location > 0 && range.length == 1 && string.length == 0)
        {
            // Stores cursor position
            UITextPosition *beginning = textField.beginningOfDocument;
            UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
            NSInteger cursorOffset = [textField offsetFromPosition:beginning toPosition:start] + string.length;

            // Save the current text, in case iOS deletes the whole text
            NSString *text = textField.text;


            // Trigger deletion
            [textField deleteBackward];


            // iOS deleted the entire string
            if (textField.text.length != text.length - 1)
            {
                textField.text = [text stringByReplacingCharactersInRange:range withString:string];

                // Update cursor position
                UITextPosition *newCursorPosition = [textField positionFromPosition:textField.beginningOfDocument offset:cursorOffset];
                UITextRange *newSelectedRange = [textField textRangeFromPosition:newCursorPosition toPosition:newCursorPosition];
                [textField setSelectedTextRange:newSelectedRange];
            }

            return NO;
        }

        return YES;
    }
like image 115
Sascha Manuel Hameister Avatar answered Nov 04 '22 18:11

Sascha Manuel Hameister


Finally figured it out for anyone looking to see how to determine when a backspace is going to clear all the characters of a secure UITextField:

UITextField:

self.passwordTextField

Private property (initialized to NO in init - probably not needed):

self.passwordFirstCharacterAfterDidBeginEditing

UITextFieldDelegate Methods:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    //if text is blank when first editing, then first delete is just a single space delete
    if([textField.text length] == 0 && self.passwordFirstCharacterAfterDidBeginEditing)
        self.passwordFirstCharacterAfterDidBeginEditing = NO;

    //if text is present when first editing, the first delete will result in clearing the entire password, even after typing text
    if([textField.text length] > 0 && self.passwordFirstCharacterAfterDidBeginEditing && [string length] == 0 && textField == self.passwordTextField)
    {
        NSLog(@"Deleting all characters");
        self.passwordFirstCharacterAfterDidBeginEditing = NO;
    }
    return YES;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    if(textField == self.passwordTextField)
    {
        self.passwordFirstCharacterAfterDidBeginEditing = YES;
    }
}

I hope this helps someone and I also hope Apple just creates a delegate method that is called when a secure text field is cleared by a delete - this seems a big cumbersome, but it works.

like image 6
crizzwald Avatar answered Nov 04 '22 18:11

crizzwald