【问题标题】:UITextField secureTextEntry - works going from YES to NO, but changing back to YES has no effectUITextField secureTextEntry - 从 YES 变为 NO,但改回 YES 无效
【发布时间】:2011-07-15 16:11:50
【问题描述】:

以上说明了一切-我将 UITextField 设置为安全,但希望为用户提供使其不安全的选项(因此,如果他们在私人区域中,他们可以确定输入的内容)。但是,假设他们错误地按下了切换开关,并想将其更改回安全模式?那是行不通的。我已经尝试了一切 - 使用 -1 而不是 YES,删除文本然后将其放回原处。我对其他想法一无所知。 [输入 rdar://9781908]

编辑:我相信这个问题自 iOS5 起已修复。

【问题讨论】:

  • // 来自设置状态的 UISwitch 的 touchUp // 在 ON->OFF 下工作,但将其更改为 OFF->ON 无效,/ 开关从然后打开 - (IBAction)secureSwitchAction:(UISwitch *)sender { BOOL isOn = sender.on; textField.secureTextEntry = isOn; }
  • 谢谢并保重。 :)

标签: uitextfield


【解决方案1】:

一定是输入焦点问题:当有焦点时,UITextField 只能改变 ON->OFF。
尝试下一个技巧来关闭->打开:

textField.enabled = NO;
textField.secureTextEntry = YES;
textField.enabled = YES;
[textField becomeFirstResponder];

编辑(dhoerl):在 iOS 9.3 中,我发现这是可行的,但有一个问题。如果您在普通视图中输入 3 个字符,然后切换到安全文本,然后键入一个字符,则 3 个预先存在的字符会消失。我尝试了各种技巧来清除,然后重置文本没有成功。我终于尝试通过剪切和粘贴来玩控制 - 粘贴到新切换到安全模式的效果很好。所以我在代码中模拟了它,现在一切正常——也不需要和响应者一起玩。这是我最终得到的结果:

    if textview should go into secure mode and the textfield is not empty {
        textField.text = ""
        textField.secureTextEntry = true

        UIPasteboard.generalPasteboard().string = password
        textField.paste(self)
        UIPasteboard.generalPasteboard().string = ""
    }

我宁愿不必做这个粘贴,但如果你希望它无缝,这是我能找到的唯一方法。

【讨论】:

  • 是的 - 我确实发现只要控件不是第一响应者,它就会按预期工作。一只小鸟告诉我,这可能会在未来的 iOS 版本中得到解决。
  • 所以我在上面测试了您的代码以代替我的修复 - textField 在禁用时显然会退出第一响应者。也就是说,附加 [textField becomeFirstResponder];导致工作解决方案比我的简单得多。谢谢!
  • 仅供参考我尝试了这个解决方案,并在将secureTextEntry设置为NO后产生了额外的空间:stackoverflow.com/questions/14220187/…
  • 这个解决方案在反复来回切换时不起作用(至少在 iOS 8.1 上)。
  • 在 iOS 8.1 上测试并且可以正常工作。仅供参考,您只需要 becomeFirstResponder 行。
【解决方案2】:

Mike R 的解决方案不错,但我更喜欢这种方法:

BOOL wasFirstResponder;
if ((wasFirstResponder = [passwordField isFirstResponder])) {
    [passwordField resignFirstResponder];
}
// In this example, there is a "show password" toggle
[passwordField setSecureTextEntry:![passwordField isSecureTextEntry]];
if (wasFirstResponder) {
    [passwordField becomeFirstResponder];
}

这样你只会在必要时再次成为FirstResponder。

【讨论】:

  • 这对我来说似乎是一个更好的解决方案,谢谢桑迪。我已经将它封装在我的应用程序的一个小函数中。
  • 我刚刚对这个答案投了赞成票,因为当我尝试第一个答案时,在将 secureTextEntry 设置为 NO 时,我的文本末尾出现了一个神秘的尾随空格。这个解决方案没有这个问题。
  • 只有我一个人在切换 OFF ==> ON 时有错误吗?如果我输入新字母,首先清除内容;-(
  • 反复来回切换时,此解决方案不起作用(至少在 iOS 8.1 上)。
【解决方案3】:

我针对这个问题输入了 rdar,但确实找到了解决方法。本质上,您必须以编程方式将“卡住”控件替换为新控件。最简单的做法是归档 viewDidLoad 中的现有控件,然后根据需要取消归档:

// do in viewDidLoad
self.passwordMemberArchive = [NSMutableData data];
NSKeyedArchiver *ka = [[NSKeyedArchiver alloc]       initForWritingWithMutableData:passwordMemberArchive];
[ka encodeObject:password];
[ka finishEncoding];
[ka release];


    // In the action method when you get the UISwitch action message ---
// when your switch changes state
if(isOn) {
    NSString *text = [NSString stringWithString:password.text];
    NSKeyedUnarchiver *kua = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    UITextField *tf = [kua decodeObject];
    [kua finishDecoding];
    [kua release];
    tf.inputAccessoryView = textField.inputAccessoryView;
    tf.frame = textField.frame;

    BOOL isFirstResponder = [textField isFirstResponder];
    [scrollView insertSubview:tf aboveSubview:textField];
    if(isFirstResponder) {
        [tf becomeFirstResponder];
    }

    [textField removeFromSuperview];
    self.password = tf;

    if([text length]) {
        if(isFirstResponder) {
            // http://stackoverflow.com/questions/1317929/insert-string-at-cursor-position-of-uitextfield
            // Get a reference to the system pasteboard
            UIPasteboard* lPasteBoard = [UIPasteboard generalPasteboard];
            // Save the current pasteboard contents so we can restore them later
            NSArray* lPasteBoardItems = [lPasteBoard.items copy];
            // Update the system pasteboard with my string
            lPasteBoard.string = text;
            // Paste the pasteboard contents at current cursor location
            [tf paste:self];
            // Restore original pasteboard contents
            lPasteBoard.items = lPasteBoardItems;
            [lPasteBoardItems release];
        } else {
            tf.text = text;
        }
    }
} else {
    textField.secureTextEntry = NO;
}

【讨论】:

  • 注意 MikeR 提供的更好的解决方案:
【解决方案4】:

对于 iOS,你永远不应该尝试“破解”东西,如果你想要的行为不是由框架提供的,改变你的想法!

首先它更容易 ^^,其次用户不会对此做出响应,然后你永远不知道下一次 iOS 更新是否会破坏它,所以它可能对你的应用程序很危险。

“您希望用户看到他在安全文本字段上输入的密码”,您可以在底部显示 UILabel 吗?还是带有明确密码的确认警报框?

【讨论】:

  • 有趣的是,该功能已在一个流行的应用程序中,评级为 5 星,在商店中使用了两年,并且 cmets 对此是积极的。请注意,可以更改选项,Apple 甚至在报告后修复了此问题。
  • 是的,功能就在这里,当然这个功能是个好主意,我从来没有说过!我只是说你应该考虑使用一种干净的方式(我的意思是 iOS 代码)来让你的功能活着!
【解决方案5】:

Sandy 解决方案的 Swift 版本。

if #available(iOS 9.2, *) {
    passwordTextField.secureTextEntry = !passwordTextField.secureTextEntry
}
else {
    let wasFirstResponder = passwordTextField.isFirstResponder()
    if wasFirstResponder {
        passwordTextField.resignFirstResponder()
    }

    passwordTextField.secureTextEntry = !passwordTextField.secureTextEntry
    if wasFirstResponder {
        passwordTextField.becomeFirstResponder()
    }
}

【讨论】:

    猜你喜欢
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    相关资源
    最近更新 更多