iOS 6 UITextField Secure - 如何检测退格清除所有字符?

时间:2013-05-27 01:36:46

标签: cocoa-touch ios6 uitextfield uitextfielddelegate

在iOS 6中,如果您在安全文本字段中键入文本,请更改为另一个文本字段,然后返回到安全文本字段并点击退格键,将删除所有字符。我对这种情况很好,但是,我试图根据此安全文本字段是否包含字符来启用/禁用按钮。我知道如何确定字段中的字符以及退格是否被命中但是我无法确定如何检测是否正在清除所有字符。

这是我用来获取字段的新文本的委托方法,但是,我似乎无法弄清楚如何获取新文本(假设新文本只是一个空白字符串)点击退格会清除所有角色。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    //returns the "new text" of the field
    NSString * text = [textField.text stringByReplacingCharactersInRange:range withString:string];
}

非常感谢任何帮助。

谢谢!

7 个答案:

答案 0 :(得分:14)

我使用这个解决方案。删除char后,它不需要局部变量并正确设置光标位置。

这是这个解决方案的混搭:


 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        if (range.location > 0 && range.length == 1 && string.length == 0)
        {
            // Stores cursor position
            UITextPosition *beginning = textField.beginningOfDocument;
            UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
            NSInteger cursorOffset = [textField offsetFromPosition:beginning toPosition:start] + string.length;

            // Save the current text, in case iOS deletes the whole text
            NSString *text = textField.text;


            // Trigger deletion
            [textField deleteBackward];


            // iOS deleted the entire string
            if (textField.text.length != text.length - 1)
            {
                textField.text = [text stringByReplacingCharactersInRange:range withString:string];

                // Update cursor position
                UITextPosition *newCursorPosition = [textField positionFromPosition:textField.beginningOfDocument offset:cursorOffset];
                UITextRange *newSelectedRange = [textField textRangeFromPosition:newCursorPosition toPosition:newCursorPosition];
                [textField setSelectedTextRange:newSelectedRange];
            }

            return NO;
        }

        return YES;
    }

答案 1 :(得分:6)

最后想知道如何确定退格何时清除安全UITextField的所有字符的任何人:

的UITextField:

self.passwordTextField

私有属性(在init中初始化为NO - 可能不需要):

self.passwordFirstCharacterAfterDidBeginEditing

UITextFieldDelegate方法:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    //if text is blank when first editing, then first delete is just a single space delete
    if([textField.text length] == 0 && self.passwordFirstCharacterAfterDidBeginEditing)
        self.passwordFirstCharacterAfterDidBeginEditing = NO;

    //if text is present when first editing, the first delete will result in clearing the entire password, even after typing text
    if([textField.text length] > 0 && self.passwordFirstCharacterAfterDidBeginEditing && [string length] == 0 && textField == self.passwordTextField)
    {
        NSLog(@"Deleting all characters");
        self.passwordFirstCharacterAfterDidBeginEditing = NO;
    }
    return YES;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    if(textField == self.passwordTextField)
    {
        self.passwordFirstCharacterAfterDidBeginEditing = YES;
    }
}

我希望这可以帮助某人,我也希望Apple只创建一个委托方法,当一个删除清除安全文本字段时调用该方法 - 这看起来很麻烦,但它确实有效。

答案 2 :(得分:3)

在iOS6 +上开始编辑时,无论您是删除还是输入文本,都会清除文本字段。如果从退格中清除文本字段,则检查替换字符串的长度是否有效,但是如果在输入文本时清除文本,则textField:shouldChangeCharactersInRange:replacementString:的范围和替换字符串参数不正确。这是我的解决方案:

1)注册textFieldTextDidChange通知。

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(textFieldTextDidChange:)
                                             name:UITextFieldTextDidChangeNotification
                                           object:nil];

2)如果文本字段是安全的并且可能已被清除,则重新调用textField:shouldChangeCharactersInRange:replacementString:委托方法。

- (void)textFieldTextDidChange:(NSNotification *)notification
{
    if (textField.secureTextEntry && textField.text.length <= 1) {
        [self.textField.delegate textField:self.textField
             shouldChangeCharactersInRange:NSMakeRange(0, textField.text.length)
                         replacementString:textField.text];
    }
}

答案 3 :(得分:1)

已接受的解决方案无法启用按钮。它实际上改变了安全文本字段的退格行为。

这个Swift解决方案确实通过正确地通知委托有关将在textField中设置的实际字符串来解决问题,包括按下退格时。然后该代表可以做出决定。

    <FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:padding="5dp">

    <android.support.design.widget.FloatingActionButton
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/box_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:backgroundTint="#ffc800"
        android:elevation="1dp"
        app:fabSize="normal"
        android:src="@drawable/ic_box"
        android:layout_marginBottom="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="5dp"
        android:layout_marginStart="16dp"/>

    <TextView
        android:layout_height="wrap_content"
        android:textColor="@android:color/background_dark"
        android:text="0"
        android:elevation="7dp"
        android:layout_gravity="top|end"
        android:layout_width="wrap_content"
        android:textStyle="normal|bold"
        android:background="@drawable/bg_text"
        android:paddingBottom="1dp"
        android:paddingTop="1dp"
        android:paddingEnd="5dp"
        android:paddingStart="5dp"
        android:textSize="12sp"
        android:layout_marginEnd="16dp"
        android:textAlignment="center"
        android:layout_marginBottom="16dp" />

</FrameLayout>

答案 4 :(得分:1)

我遇到了同样的问题,我想检测退格区何时清除所有字符,以便我可以启用禁用屏幕上的其他按钮。所以这就是我实现它的方式。

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    _checkForDelete = NO;
    if (textField.isSecureTextEntry && textField.text.length > 0) {
        _checkForDelete = YES;
    }
    return YES;
}

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (_checkForDelete && string.length == 0) {
        _checkForDelete = NO;
        //Do whatever you want to do in this case, 
        //because all the text is going to be cleared.
    }
    return YES
}

这个解决方案是不同的,因为它允许你在安全字段中已经包含一些文本并且你正在尝试编辑它时采取行动,而不是在上面接受的答案中,即使你按下退格键,你也会进入块状态已编辑字段,不会清除整个文本但只删除一个字符。使用我的方法,您可以选择在此特殊情况下执行操作,但它也不会影响本机流。

答案 5 :(得分:0)

发布我的替代解决方案,因为我确切地将问题作为OP,并且发现我没有在所选答案中详细说明任何光标位置更改。

下面是UITextFieldDelegate方法,我调用自定义委托方法didChangeValueForTextField作为我要启用的按钮是在此类之外。

实施UITextFieldDelegate的类

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *newValue = [textField.text stringByReplacingCharactersInRange:range withString:string];
BOOL shouldReturn = YES;

if (range.location > 0 && range.length == 1 && string.length == 0){
    [textField deleteBackward];

    if ([textField.text isEmptyCheck]) {  // Check if textField is empty
        newValue = @"";
    }

    shouldReturn = NO;
}

if(self.delegate && [self.delegate respondsToSelector:@selector(didChangeValueForField:withNewValue:)]) {
    [self.delegate didChangeValueForField:textField withNewValue:newValue];
}

return shouldReturn;

}

关键是检测安全字段单字符删除和触发字段清除的安全字段单字符删除之间的区别。在中检测上面的委托方法是必要的。

类包含按钮以启用

 - (void)didChangeValueForField:(UITextField *)textField withNewValue:(NSString *)value {
  // Update values used to validate/invalidate the button.
  // I updated a separate model here.

  // Enable button based on validity
  BOOL isEnabled = [self allFieldsValid];  //  Check all field values that contribute to the button being enabled.

  self.myButton.enabled = isEnabled;

}

答案 6 :(得分:-1)

swift3.0 - 它有效。

func textField(_ textField:UITextField,shouldChangeCharactersIn范围:NSRange,replacementString string:String) - &gt;布尔{

    if textField == passwordTextfield {

        if range.location > 0 && range.length == 1 && string.characters.count == 0 {

            if let textString = textField.text {
                // iOS is trying to delete the entire string
                let index = textString.index(textString.endIndex, offsetBy: -1)
                textField.text = textString.substring(to: index)
                return false
            }

        }else if range.location == 0 {
            return true
        }else {
            if let textString = textField.text {
                textField.text = textString + string
                return false
            }
        }


    }
    return true
}