Choosing a keyboard language for UITextField with secureTextEntry

I am having a problem changing the language for the password field. In my application I need to enter a username / password in Hebrew without worrying about the current locale. When I try to enter the login, then everything is in order, I can change the keyboard to Hebrew and enter the login. But when I try to enter a password in protected textField, the keyboard appears without a language selection button, so I can only enter English letters.

The fact is that logins / passwords can be in English or Hebrew.

How can I put a language select button in a protected textField?

+6
source share
3 answers

I did not find a solution. I had to make this fragment:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string]; NSString *pass = password; pass = [pass stringByReplacingCharactersInRange:range withString:string]; [password release]; password = nil; password = [[NSString stringWithString:pass] retain]; [self hideTextInTextFieldExceptOne:string]; [self performSelector:@selector(hideTextInTextField) withObject:self afterDelay:1.0]; return NO; } - (void)hideTextInTextFieldExceptOne:(NSString *)string { int lenght = [passwordTextField.text length]; for (int i = 0; i < lenght-1; i++) { NSRange range = NSMakeRange(i, 1); passwordTextField.text = [passwordTextField.text stringByReplacingCharactersInRange:range withString:@"*"]; } } - (void)hideTextInTextField { NSUInteger lenght = [passwordTextField.text length]; passwordTextField.text = @""; for (int i = 0; i < lenght; i++) { passwordTextField.text = [passwordTextField.text stringByAppendingString:@"*"]; } } 
+6
source

@Lonlywolf optimized answer to the best performance code: Only two methods have been optimized, where there are loops that slowed the program down when entering more than 30 characters

 - (void)hideTextInTextFieldExceptOne:(NSString *)string { int lenght = [passwordTextField.text length]; if (lenght -1 > 0) { NSString *resultString = @""; for (int i = 0; i < lenght-1; i++) { resultString = [resultString stringByAppendingFormat:@"*"]; } NSRange range = NSMakeRange(0, lenght - 1); passwordTextField.text = [fieldPassword.text stringByReplacingCharactersInRange:range withString:resultString]; } } - (void)hideTextInTextField { int lenght = [passwordTextField.text length]; if (lenght > 0) { NSString *resultString = @""; for (int i = 0; i < lenght; i++) { resultString = [resultString stringByAppendingFormat:@"*"]; } passwordTextField.text = resultString; } } 
+1
source

Unfortunately, the solution posted here does not work for languages ​​with compound characters (such as Korean).

Languages ​​such as Korean (Hangul) have a composite character, where each letter consists of several characters. For example, β€œγ…β€, β€œγ…β€ and β€œγ„΄β€ are separate characters, but when combined, they become β€œλ§Œβ€, which are treated as a single letter.

Here is a solution that works for all languages.

Put the UILabel on top of the UITextField. Set the UILabel view a little less than the UITextField so that it is inside the UITextField, but still hides the text of the UITextField. TextField: shouldChangeCharactersInRange: withReplacementString is called before the text completes. This means that we need to fill in the text ourselves. This is more difficult to do with composite language languages ​​such as Korean. Instead, register for a UITextFieldTextDidChangeNotification, which will be called when new text appears on the UITextField.

 @interface MKSecureTextField()<UITextFieldDelegate> @property (nonatomic, strong) UITextField* textField; @property (nonatomic, strong) UILabel* hideLabel; @property (nonatomic, strong) NSTimer* hideTimer; @property (nonatomic, strong) NSTimer* blinkTimer; @end @implementation MKSecureTextField - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; _textField.userInteractionEnabled = YES; _textField.borderStyle = UITextBorderStyleRoundedRect; _textField.font = [UIFont systemFontOfSize:14]; _textField.placeholder = @"enter text"; _textField.autocorrectionType = UITextAutocorrectionTypeNo; _textField.keyboardType = UIKeyboardTypeDefault; _textField.returnKeyType = UIReturnKeyDone; _textField.clearButtonMode = UITextFieldViewModeWhileEditing; _textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; _textField.delegate = self; self.hideLabel = [[UILabel alloc] initWithFrame:CGRectMake(6, 5, frame.size.width-10, frame.size.height-12)]; _hideLabel.backgroundColor = [UIColor whiteColor]; [self addSubview:_textField]; [self addSubview:_hideLabel]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldDidChange:) name:UITextFieldTextDidChangeNotification object:nil]; } return self; } 

When UITextFieldTextDidChangeNotification is received, hide everything except the last character. Hidden text will be installed programmatically on UILabel. Also plan a timer that will hide the last character. This timer is invalid if more text is typed.

 - (void)textFieldDidChange:(NSNotification*)notification { UITextField* textField = notification.object; if (textField == _textField) { NSString* text = textField.text; [self hideExceptLastCharacter:text]; [self.hideTimer invalidate]; self.hideTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(hideLastCharacter) userInfo:nil repeats:NO]; } } 

UILabel does not have a blinking cursor. Therefore, we imitate its alternation between '|' and space. The blinking cursor is placed when editing begins, and is deleted when editing is completed.

 - (void)textFieldDidBeginEditing:(UITextField *)textField { if (_hideLabel.text == nil) { _hideLabel.text = @"|"; } else { _hideLabel.text = [_hideLabel.text stringByAppendingString:@"|"]; } self.blinkTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(blinkCursor) userInfo:nil repeats:YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { NSRange range; range.location = _hideLabel.text.length - 1; range.length = 1; _hideLabel.text = [_hideLabel.text stringByReplacingCharactersInRange:range withString:@""]; [_blinkTimer invalidate]; } - (void)blinkCursor { if (_hideLabel.text.length > 0) { static BOOL visible = YES; NSRange range; range.location = _hideLabel.text.length - 1; range.length = 1; if (visible) { _hideLabel.text = [_hideLabel.text stringByReplacingCharactersInRange:range withString:@" "]; } else { _hideLabel.text = [_hideLabel.text stringByReplacingCharactersInRange:range withString:@"|"]; } visible = !visible; } } 

Symbols, with the exception of the latter, are hidden. This is installed on UILabel. UITextField remains untouched.

 - (void)hideExceptLastCharacter:(NSString*)string { int length = [_textField.text length]; NSString* s = @""; for (int i = 0; i < length-1; i++) { s = [s stringByAppendingString:@"●"]; } if (_textField.text.length > 0) { _hideLabel.text = [s stringByAppendingString:[_textField.text substringFromIndex:_textField.text.length-1]]; _hideLabel.text = [_hideLabel.text stringByAppendingString:@"|"]; } else { _hideLabel.text = @"|"; } } - (void)hideLastCharacter { if (_hideLabel.text.length > 1) { NSRange range; range.location = [_hideLabel.text length]-2; range.length = 1; _hideLabel.text = [_hideLabel.text stringByReplacingCharactersInRange:range withString:@"●"]; } } - (void)dealloc { [_hideTimer invalidate]; [_blinkTimer invalidate]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } @end 

See the Github project for help.

+1
source

Source: https://habr.com/ru/post/893582/


All Articles