在secureTextEntry切换之后,UITextField具有尾随空格

时间:2013-01-08 16:59:28

标签: ios uitextfield

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

我在这里跟踪了这个例子(投票数最多):UITextField secureTextEntry - works going from YES to NO, but changing back to YES has no effect

但是,当我将secureTextEntry设置为NO时,在那里写入的任何文本最后都会有一个空格。将secureTextEntry设置为YES时,这似乎不是问题。

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

重要说明:在调试器中,文本的字符串值显示为,不带尾随空格,如下所示:

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

我尝试修剪空白(每avoid middle whitespace in UITextField),但它没有效果。

18 个答案:

答案 0 :(得分:41)

我刚遇到这个案子,最后解决了这个问题。

适用于最新的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;
}

Swift 3 +

   // Workaround to refresh cursor

    let currentText: String = self.userPassword.text!
    self.userPassword.text = "";
    self.userPassword.text = currentText
希望它有所帮助!

答案 1 :(得分:13)

PRE-iOS-8.0 (日期解决方案) ...在按钮的操作方法中(在secureTextEntry YES和NO之间切换),只需设置{{1} } UITextField属性为其当前text值。虽然这可能看起来多余而且有点像黑客,但这会将光标重新绘制在正确的位置。以下是您的按钮操作方法现在应该是什么样子的示例...

text

POST-iOS-8.0 ...从iOS 8.0开始,-(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]; } ' s UITextField setter在使用等于其当前字符串的字符串调用时不再重绘光标值。现在,我们需要更进一步,实际更改text值,然后再重置它。将上述text行替换为类似这些行。

setText:

答案 2 :(得分: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.

答案 3 :(得分: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;
}

答案 4 :(得分:4)

你可以这样解决:

NSString *currentText = self.textfield.text;
self.textfield.text = @"";
self.textfield.text = currentText;

答案 5 :(得分: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;
}

答案 6 :(得分: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中使用的

答案 7 :(得分:2)

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

pwdTextField.text  = pwdTextField.text

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

let str = pwdTextField.text
pwdTextField.text = str + " "
pwdTextField.text = str

答案 8 :(得分:2)

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

if (self.passwordText.isFirstResponder) {
    [self.passwordText resignFirstResponder];
    [self.passwordText becomeFirstResponder];
}

答案 9 :(得分: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];

答案 10 :(得分:1)

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

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

答案 11 :(得分: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
}

答案 12 :(得分:0)

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

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

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

答案 13 :(得分: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)
}

答案 14 :(得分: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];
}

答案 15 :(得分:0)

我正在使用它,工作正常。

[self.yourTextField becomeFirstResponder];

答案 16 :(得分:0)

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

所以我使用了这段代码

partial void btnShowPassword_ToutchUpInside (UIButton sender)
    {
        if (TxtPassword.SecureTextEntry == true) {
            TxtPassword.SecureTextEntry = false;
            TxtPassword.Text = TxtPassword.Text;
        } else {
            TxtPassword.SecureTextEntry = true;
        }
    }

答案 17 :(得分:0)

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

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

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

在iOS8,iOS9上测试过。 希望它有所帮助!