【问题标题】:Show/Hide Password Toggle. Bug or Feature?显示/隐藏密码切换。错误或功能?
【发布时间】:2014-05-01 19:00:59
【问题描述】:

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

如果密码被隐藏并且输入了一半(例如“abc”)并且用户点击切换按钮以显示密码并继续输入,那么新字符(例如“def”)将添加到初始字符的末尾条目(制作“abcdef”)。一切顺利。

但是,如果显示密码并且输入了一半(例如“abc”)并且用户点击切换按钮以隐藏密码并继续输入,那么新字符(例如“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];
    }
}

【问题讨论】:

  • 我没有隐藏该字段,仅隐藏它包含的文本。出现这种情况是因为用户在切换显示/隐藏按钮后仍希望继续向字段添加文本,因此不适合关闭键盘并结束编辑。
  • 我认为@Wain 的回答可能是最好的。如果用户点击了隐藏按钮,您不应该让他们有机会继续输入。
  • 因此,如果用户开始输入可见密码并意识到有人可能正在观看,则切换为隐藏密码,那么您认为用户期望能够完成密码输入是不合理的?
  • 这不是我要说的。当用户隐藏文本时,你应该把它放在他们不能再发短信的地方(就你所说的情况,他们可能会点击错误的按钮并破坏他们的密码。)一旦他们点击“显示”按钮,只需再次加载键盘,这样他们就可以继续输入他们的信息

标签: objective-c uitextfield


【解决方案1】:

我找不到它的文档,但我记得更改安全条目设置也会更改 clearsOnInsertion

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

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

【讨论】:

  • 奇怪的行为。覆盖所写的内容,假设用户无法记住他们输入的内容,如果他们看不到的话。摆弄clearsOnInsertionclearsOnBeginEditing 似乎也不会影响行为。我想我只会告诉用户“这是为了你好。Apple 说你的记忆跨度太短,无法点击按钮并继续输入。”。
【解决方案2】:

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

更改 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;
}

如果您需要任何说明或发现任何错误,请告诉我。 ;) 尽情享受吧!

【讨论】:

    猜你喜欢
    • 2020-12-29
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 1970-01-01
    • 2022-10-24
    相关资源
    最近更新 更多