显示/隐藏密码切换。错误还是功能?

时间:2014-03-24 12:14:43

标签: objective-c uitextfield

我正在使用XCode和Objective-C开发iPad应用程序。我有一个UI,其中包括密码输入字段和显示/隐藏按钮(代码如下所示)。测试人员指出了以下不一致的行为。

如果密码被隐藏并且输入了一半(例如" abc")并且用户点击切换按钮以显示密码并继续键入然后输入新字符(例如" def&#34 ;)被添加到初始条目的末尾(制作" abcdef")。一切都很好。

但是,如果显示密码并输入一半(例如" abc")并且用户点击切换按钮隐藏密码并继续输入新字符(例如" def& #34;)替换初始条目(制作" def")。因此,显示/隐藏切换不仅会显示或隐藏文本,还会在输入下一个字符时更改UITextField的行为(追加/清除并重新开始)。

我可以想到(不是很好)这种行为是出于设计的原因,但没有人能够证明它是好的。任何人都可以建议快速修复(这可以防止切换隐藏文本操作清除部分输入的密码)?

- (IBAction)togglePasswordReveal:(id)sender
{
    if ([self.revealButton.titleLabel.text isEqualToString:@"Show"]) {
        self.password.secureTextEntry = NO;
        [self.revealButton setTitle:@"Hide" forState:UIControlStateNormal];
    }
    else {
        self.password.secureTextEntry = YES;
        [self.revealButton setTitle:@"Show" forState:UIControlStateNormal];
    }
}

2 个答案:

答案 0 :(得分:2)

我无法找到相关文档,但我记得更改安全条目设置也会更改clearsOnInsertion

查看设置clearsOnInsertion和/或使用委托方法textFieldShouldClear:textField:shouldChangeCharactersInRange:replacementString:来修改此行为。

我猜逻辑是用户通常不会确定他们之前键入的内容,因为他们无法看到字符,所以sage选项是强制用户重新开始。

答案 1 :(得分:1)

面临同样的问题。这是我的理解和解决方案。

更改clearsOnInsertion,clearsOnBeginEditing对安全文本字段没有影响。

在文本字段上切换secureTextEntry会导致它失去响应者状态并再次成为第一响应者。因此,任何新文本都会清除当前文本。

出于安全原因,我通过覆盖textField:shouldChangeCharactersInRange:replacementString:和其他一些更改解决了这个问题。我在编辑时使用右视图显示切换按钮。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    // Customize text entry in password field
    if (textField == self.passwordTf) {
        NSString *currentString = textField.text;

        // Handle inserting, deleting characters
        textField.text = [currentString stringByReplacingCharactersInRange:range withString:string];

        // Setting the cursor at the right place
        NSRange selectedRange = NSMakeRange(range.location + string.length, 0);
        UITextPosition* from = [textField positionFromPosition:textField.beginningOfDocument offset:selectedRange.location];
        UITextPosition* to = [textField positionFromPosition:from offset:selectedRange.length];
        textField.selectedTextRange = [textField textRangeFromPosition:from toPosition:to];

        // If password cleared, updated edited status
        if (textField.text.length == 0) {
            passwordEdited = YES;
        }

        [self toggleButtonStatus];

        return NO;
    }

    return YES;
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{        
    // Reset password edited status on begin editing
    if (textField == self.passwordTf &&
        [textField.text length] > 0) {
        passwordEdited = NO;
    }

    [self toggleButtonStatus];
}

- (void)textFieldDidChange:(NSNotification*)notification
{
    UITextField *textField = notification.object;

    // If password cleared, updated edited status
    if (self.passwordTf == textField &&
        textField.text.length == 0) {
        passwordEdited = YES;
    }

    [self toggleButtonStatus];
}

- (void)toggleButtonStatus
{
    // For security, only show eye button if not saved password
    if (passwordEdited) {
        self.passwordTf.clearButtonMode = UITextFieldViewModeNever;
        self.passwordTf.rightViewMode = UITextFieldViewModeWhileEditing;
    } else {
        self.passwordTf.clearButtonMode = UITextFieldViewModeWhileEditing;
        self.passwordTf.rightViewMode = UITextFieldViewModeNever;
    }
}

作为奖励,这里是切换按钮的代码,在切换时更新光标位置。

eyeButton = [UIButton buttonWithType:UIButtonTypeCustom];
eyeButton.frame = CGRectMake(0, 0, 44, 44);
eyeButton.imageEdgeInsets = UIEdgeInsetsMake(0, 16, 0, 0);
[eyeButton addTarget:self action:@selector(eyeButtonPressed:) forControlEvents:UIControlEventTouchDown];
[eyeButton addTarget:self action:@selector(eyeButtonReleased:) forControlEvents:UIControlEventTouchUpInside];
[eyeButton addTarget:self action:@selector(eyeButtonReleased:) forControlEvents:UIControlEventTouchUpOutside];
[eyeButton addTarget:self action:@selector(eyeButtonReleased:) forControlEvents:UIControlEventTouchCancel];
[eyeButton addTarget:self action:@selector(eyeButtonReleased:) forControlEvents:UIControlEventTouchDragExit];

...

self.passwordTf.rightView = eyeButton;
self.passwordTf.rightViewMode = UITextFieldViewModeWhileEditing;

- (void)eyeButtonPressed:(id)sender {
    UIFont *textFieldFont = ...
    UIColor *textFieldColor = ...

    // Hack to update cursor position
    self.passwordTf.defaultTextAttributes = @{NSFontAttributeName: textFieldFont,
                                              NSForegroundColorAttributeName: textFieldColor};

    // Change secure entry
    self.passwordTf.secureTextEntry = NO;
}

- (void)eyeButtonReleased:(id)sender {
    UIFont *textFieldFont = ...
    UIColor *textFieldColor = ...

    // Hack to update cursor position
    self.passwordTf.defaultTextAttributes = @{NSFontAttributeName: textFieldFont,
                                              NSForegroundColorAttributeName: textFieldColor};
    // Change secure entry
    self.passwordTf.secureTextEntry = YES;
}

如果您需要任何澄清或发现任何错误,请与我们联系。 ;) 享受!