2

I want to override the key pressed event to force that, even when a capital key is pressed, the resulting output is still lowercase.

brandonscript
  • 68,675
  • 32
  • 163
  • 220

2 Answers2

7

This should work (you should also set textfield.autocapitalizationType=UITextAutocapitalizationTypeNone)

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField==_usernameTextfield || textField==_emailTextfield) {
        NSRange lowercaseCharRange;
        lowercaseCharRange = [string rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]];

        if (lowercaseCharRange.location != NSNotFound) {
            // some uppercase chars where found, need to replace

            UITextPosition *beginning = textField.beginningOfDocument;
            UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
            // new cursor location after insert/paste/typing
            NSInteger cursorOffset = [textField offsetFromPosition:beginning toPosition:start] + string.length;

            // convert whole text to lowercase and update the textfield
            textField.text = [textField.text stringByReplacingCharactersInRange:range
                                                                 withString:[string lowercaseString]];

            // now reposition the cursor
            UITextPosition *newCursorPosition = [textField positionFromPosition:textField.beginningOfDocument offset:cursorOffset];
            UITextRange *newSelectedRange = [textField textRangeFromPosition:newCursorPosition toPosition:newCursorPosition];
            [textField setSelectedTextRange:newSelectedRange];
            return NO;
        }
    }
    return YES;
}
Orn Arnarson
  • 136
  • 1
  • 5
  • i upvoted ur answer. but you should check this accepted Answer http://stackoverflow.com/questions/21092182/uppercase-characters-in-uitextfield . you just need to textField.text = [textField.text stringByReplacingCharactersInRange:range withString:[string lowercaseString]]; and return NO; – Vatsal Shukla May 20 '16 at 07:21
4

Solution is to add a selector for textFieldDidChange:

[self addTarget:self
                  action:@selector(textFieldDidChange:)
        forControlEvents:UIControlEventEditingChanged];

And in the textFieldDidChange event, add the following:

- (void)textFieldDidChange:(UITextField*)textField {
    textField.text = [textField.text lowercaseString];
}

Or you can use the Interface Builder @IBAction Editing Changed

Swift 2 version:

@IBAction func textChanged(sender: UITextField) {
    sender.text = sender.text?.lowercaseString
}  
brandonscript
  • 68,675
  • 32
  • 163
  • 220
  • This is not the best approach. It would be better to implement the `textField:shouldChangeCharactersInRange:replacementString:` method and update each change as it happens. – rmaddy Sep 18 '14 at 01:42
  • That only fires after the text appears in the box though, not pleasant UX. – brandonscript Sep 18 '14 at 01:43
  • My approach actually forces the lowercase as the user types. – rmaddy Sep 18 '14 at 02:02
  • Weird.. I was doing that before returning the BOOL and it wasn't updating. Post an answer if you like. – brandonscript Sep 18 '14 at 02:05
  • If you explicitly modify the text field in the `textField:shouldChangeCharactersInRange:replacementString:`, return `NO`. – rmaddy Sep 18 '14 at 02:18
  • 1
    The problem with this approach is that if the user enters a character in the middle of the text, it jumps the selection point to the end of the text. – matt Oct 02 '17 at 00:31