Выбор языка клавиатуры для UITextField с secureTextEntry

Я застрял с проблемой изменения языка для поля пароля. В моем приложении мне нужно ввести логин / пароль на иврите, не заботясь о текущей локали. Когда я пытаюсь ввести логин, тогда все в порядке, я могу изменить клавиатуру на иврит и ввести логин. Но когда я пытаюсь ввести пароль в защищенном текстовом поле, клавиатура появляется без кнопки выбрать язык, поэтому я могу вводить только английские буквы.

дело в том, что логины/пароли могут быть на английском или еврей.

Как я могу поместить кнопку выбрать язык в защищенное текстовое поле?

3 ответов


не нашел решения. Пришлось сделать этот фрагмент:

-(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:@"*"];
}
}

оптимизированный @ lonlywolf ответ на лучший код производительности: Оптимизированы только два метода, где есть циклы, которые замедляют работу программы при вводе более 30 символов

- (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;
    }
}

к сожалению, решение опубликовано здесь не работает для языков с составными символами (например, корейский).

языки, такие как корейский (хангыль), имеют составной символ, где каждая буква состоит из нескольких символов. Например, "ㅁ", " ㅏ " и " ㄴ "- это отдельные символы, но при объединении они становятся "만", которое рассматривается как одна буква.

вот решение, которое работает для всех языков.

поместите UILabel поверх Поле UITextField. Установите кадр UILabel немного меньше, чем UITextField, чтобы он находился внутри UITextField, но все еще скрывает текст UITextField. TextField:shouldChangeCharactersInRange: withReplacementString вызывается до завершения текста. Это означает, что мы должны завершить текст сами. Это сложнее сделать с составными языками символов, такими как корейский. Вместо этого зарегистрируйтесь для UITextFieldTextDidChangeNotification, который будет вызываться после появления нового текста на в поле 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;
}

когда UITextFieldTextDidChangeNotification получен, скрыть все, кроме последнего символа. Скрытый текст будет программно установлен на UILabel. Кроме того, запланируйте таймер, который скроет последний символ. Этот таймер недействителен, если вводится больше текста.

- (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 не имеет мигающего курсора. Поэтому мы эмулируем его, чередуя " | " и пространство. Мигающий курсор помещается, когда начинается редактирование, и удаляется по окончании редактирования.

- (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;
    }
}

символы за исключением последнего скрыта. Это установлено на UILabel. UITextField остается нетронутым.

- (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

посмотреть этот проект Github для справки.