35

我有一个在显示/隐藏模式之间切换的按钮(即在secureTextEntry NO 和YES 之间切换UITextField)。其目的是允许用户查看他们输入的密码。

我在这里遵循了示例(投票数最高):UITextField secureTextEntry - 从 YES 变为 NO,但改回 YES 无效

但是,当我将 secureTextEntry 设置为 NO 时,在此处写入的任何文本都以空格结尾。将secureTextEntry 设置为YES 时,这似乎不是问题。

例如,如果我在 setSecureTextEntry 设置为 NO 时输入文本“mypassword”,然后将其切换为 YES,用户将看到 **********(10 个点),这是正确的。如果我将SecureTextEntry 设置为NO,用户将看到“mypassword”(末尾有一个空格,或者至少光标向右移动了一个空格)。

重要提示: 在调试器中,文本的字符串值出现时没有尾随空格,如下所示:

(lldb) expr self.passwordText.text
(NSString *) $0 = 0x1d8450e0 @"mypassword"

我试过修剪空格(避免 UITextField 中的中间空格),但它没有效果。

4

18 回答 18

42

我刚刚遇到这种情况,终于解决了这个问题。

适用于最新的 iOS SDK,iOS 8.1

首先,根本没有尾随空格。

点(在 SecureEntry 中显示)字符和普通字符具有不同的宽度,并且在您切换 isSecureEntry 开关后,光标没有刷新它的位置。

所以我使用这个解决方法来解决这个问题。

- (void)toggle
{
    NSString *tmpString;
    [self.passwordTextField setSecureTextEntry:!self.passwordTextField.isSecureTextEntry];
    if (self.passwordTextField.isSecureTextEntry) {
       // do stuffs
    } else {
       // do other stuffs
    }
    // Workaround to refresh cursor
    tmpString = self.passwordTextField.text;
    self.passwordTextField.text = @" ";
    self.passwordTextField.text = tmpString;
}

斯威夫特 3+

   // Workaround to refresh cursor

    let currentText: String = self.userPassword.text!
    self.userPassword.text = "";
    self.userPassword.text = currentText

希望能帮助到你!

于 2014-12-15T02:43:57.097 回答
13

PRE-iOS-8.0 (过时的解决方案)secureTextEntry ...在按钮的操作方法中(在YES 和 NO之间切换),只需将UITextField'text属性设置为其当前text值。尽管这可能看起来多余并且有点像 hack,但这会在正确的位置重新绘制光标。这是按钮的操作方法现在应该是什么样子的示例...

-(void)toggleButtonPressed:(UIButton*)sender
{
    // Toggle between secure and not-so-secure entry
    self.toggleButton.selected = !self.toggleButton.selected;
    self.textfield.secureTextEntry = !self.toggleButton.selected;

    // * Redundant (but necessary) line *
    [self.textfield setText:self.textfield.text];
}

POST-iOS-8.0... 从 iOS 8.0 开始,当使用等于其当前字符串值的字符串调用时,似乎UITextField's textsetter 不再重绘光标。现在,我们需要更进一步,text在再次重置之前实际更改值。setText:用类似这些行的内容替换上面的行。

// * Extra redundant (but necessary) lines *
NSString *currentText = self.textfield.text;
[self.textfield setText:@"Arbitrary string..."]; // Change the value
[self.textfield setText:currentText]; // Reset the value
于 2014-03-20T15:33:23.033 回答
8

我有一个干净的解决方案,不会text因为UITextField.

用这种风格包裹它们。

[self.passwordTextField resignFirstResponder]; // first resign its first responder.

// change `secureTextEntry` property's value if necessary.

if (self.passwordTextField.secureTextEntry) {
    self.passwordTextField.secureTextEntry = NO;
    self.passwordEcryptButton.selected = YES;
}else{
    self.passwordTextField.secureTextEntry = YES;
    self.passwordEcryptButton.selected = NO;
}

[self.passwordTextField becomeFirstResponder];  // finally gain its first responder again.
于 2015-11-30T02:57:45.403 回答
6

为了解决 iOS 中的这个错误,您可以简单地执行以下操作(适用于任何 iOS 版本):

- (IBAction)toggleSecureTextEntry:(UIButton *)button
{
    self.textField.secureTextEntry = !self.textField.secureTextEntry;
    NSString *originalText = self.textField.text;
    self.textField.text = nil;
    self.textField.text = originalText;
}
于 2015-06-16T10:35:51.320 回答
4

你可以像这样修复它:

NSString *currentText = self.textfield.text;
self.textfield.text = @"";
self.textfield.text = currentText;
于 2015-09-29T15:13:54.657 回答
3

这适用于我在 iOS 8 上

if (self.passwordTextField.secureTextEntry) {
    // Display password and keep selected text range
    UITextRange *selectedTextRange = self.passwordTextField.selectedTextRange;
    NSString *password = self.passwordTextField.text;
    self.passwordTextField.secureTextEntry = NO;
    self.passwordTextField.text = [@"" stringByPaddingToLength:password.length withString:@" " startingAtIndex:0]; // Done for carret redrawing
    self.passwordTextField.text = password;
    self.passwordTextField.selectedTextRange = selectedTextRange;
}
else {
    // Hide password and keep selected text range
    UITextRange *selectedTextRange = self.passwordTextField.selectedTextRange;
    NSString *password = self.passwordTextField.text;
    self.passwordTextField.secureTextEntry = YES;
    self.passwordTextField.text = [@"" stringByPaddingToLength:password.length withString:@" " startingAtIndex:0]; // Done for carret redrawing
    self.passwordTextField.text = password;
    self.passwordTextField.selectedTextRange = selectedTextRange;
}
于 2014-10-09T09:10:24.500 回答
3
UITextPosition *beginning = [self.passwordField beginningOfDocument];
[self.passwordField setSelectedTextRange:[self.passwordField textRangeFromPosition:beginning
                                                                        toPosition:beginning]];

UITextPosition *end = [self.passwordField endOfDocument];
[self.passwordField setSelectedTextRange:[self.passwordField textRangeFromPosition:end
                                                                        toPosition:end]];

这是我在 iOS 8 上使用的

于 2014-12-03T10:23:48.973 回答
2

当我们更改 textfield.secureTextEntry 属性时,插入符号位置不会更新。为了解决这个问题,下面的代码曾经在 IOS 8 之前工作:

pwdTextField.text  = pwdTextField.text

现在没有了。似乎 IOS 8 检测到新值等于旧值并且什么都不做。因此,要使其再次工作,我们必须实际更改该值。这是适合我的快速版本。

let str = pwdTextField.text
pwdTextField.text = str + " "
pwdTextField.text = str
于 2014-12-03T20:17:48.860 回答
2

这是解决此问题的另一种可能性,其中 self.passwordText 是 UITextField:

if (self.passwordText.isFirstResponder) {
    [self.passwordText resignFirstResponder];
    [self.passwordText becomeFirstResponder];
}
于 2015-02-20T14:10:35.827 回答
1

似乎引用链接中的第二个解决方案在实施时具有不添加额外空间的所需行为:

https://stackoverflow.com/a/8495888/738190

于 2013-01-08T19:21:26.160 回答
1

这在我的情况下有效

    BOOL wasFirstResponder = [self.passwordTextField isFirstResponder];
    if([self.passwordTextField isSecureTextEntry])
    {
        //This three lines are key
        self.passwordTextField.delegate = nil;
        [self.passwordTextField resignFirstResponder];
        self.passwordTextField.delegate = self;
    }

    [self.passwordTextField setSecureTextEntry: !self.passwordTextField.isSecureTextEntry];
    if(wasFirstResponder)
        [self.passwordTextField becomeFirstResponder];
于 2015-06-18T13:19:26.920 回答
1

Swift UITextField 扩展:

extension UITextField {
    func toggleSecureEntry() {
        let wasFirstResponder = isFirstResponder

        if wasFirstResponder { resignFirstResponder() }
        isSecureTextEntry.toggle()
        if wasFirstResponder { becomeFirstResponder() }
    }
}

设置 textField.text 解决方案在某些情况下也有效,但不适合我的需要(带有两个文本字段的自定义字体。导致字体更改和运行时出现故障。)也添加在这里。

func toggleSecureEntry() {
    isSecureTextEntry.toggle()
    let originalText = text
    text = nil
    text = originalText
}
于 2016-05-22T08:44:36.873 回答
0

为了让光标正确重新定位,设置字体属性似乎对我有用。

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

// Change secure entry
self.passwordTf.secureTextEntry = !self.passwordTf.secureTextEntry;

在 iOS8、iOS9 上测试。希望能帮助到你!

于 2015-09-26T09:37:45.210 回答
0

每次在 UITextField 中设置文本时,都会更新光标位置

所以我使用了这段代码

partial void btnShowPassword_ToutchUpInside (UIButton sender)
    {
        if (TxtPassword.SecureTextEntry == true) {
            TxtPassword.SecureTextEntry = false;
            TxtPassword.Text = TxtPassword.Text;
        } else {
            TxtPassword.SecureTextEntry = true;
        }
    }
于 2016-04-13T07:26:32.353 回答
0

我正在使用这个,工作正常。

[self.yourTextField becomeFirstResponder];
于 2016-08-31T14:13:27.670 回答
0

这是解决方案:

- (void)showHidePassword:(UIButton *)sender {
    EDSignUpCell *cell = [self.signUpTblView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]];
    if(!TRIM_SPACE(cell.cellTextField.text).length) {return;}
    [cell.showHidePasswordBtn setSelected:!cell.showHidePasswordBtn.isSelected];
    cell.cellTextField.secureTextEntry = cell.showHidePasswordBtn.isSelected;
    [cell.cellTextField setText:cell.cellTextField.text];
    [cell.cellTextField becomeFirstResponder];
}
于 2018-06-25T07:55:47.593 回答
0

斯威夫特 4

Bug 正在雷达上,也有解决方法的解释:http ://www.openradar.me/38465011

以下是如何本地更新插入符号(光标)位置的临时解决方法。

// update caret position
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
    let (beginning, end) = (self.beginningOfDocument, self.endOfDocument)

    self.selectedTextRange = self.textRange(from: beginning, to: end)
    self.selectedTextRange = self.textRange(from: end, to: end)
}
于 2018-08-17T12:54:16.263 回答
0

我有一个类似的问题,并意识到这是因为我在设置 secureTextEntry 属性之前更新了文本。如果 textField 使用secureTextEntry,它会在它所在的位置绘制插入符号,这是有道理的。

我没有阅读整个问题,也没有访问 OP 链接的解决方案,但如果其他人遇到与我相同的问题:

在设置 secureTextEntry 属性尝试更新您的文本。

于 2019-04-23T17:14:25.703 回答