代码之家  ›  专栏  ›  技术社区  ›  marcc

在空的uitextfield中检测退格

  •  111
  • marcc  · 技术社区  · 14 年前

    有什么方法可以检测 退格 / 删除 在iPhone键盘上按 UITextField 那是空的?我想知道什么时候 退格 只有在 输入框 是空的。


    根据@alex reynolds在评论中的建议,我在创建文本字段时添加了以下代码:

    [[NSNotificationCenter defaultCenter] addObserver:self
              selector:@selector(handleTextFieldChanged:)
                  name:UITextFieldTextDidChangeNotification
                object:searchTextField];
    

    收到此通知( handleTextFieldChanged 函数),但当我按下 退格 在空字段中键入。有什么想法吗?


    这个问题似乎有些困惑。我想收到通知时 退格 按键。就是这样。但解决方案也必须在 输入框 已为空。

    24 回复  |  直到 5 年前
        1
  •  33
  •   Andrew    14 年前

    这可能是一个长期的尝试,但它可以工作。尝试将文本字段的文本设置为零宽度空格字符 \u200B . 当在一个显示为空的文本字段上按退格键时,它实际上会删除您的空间。然后你可以重新插入空间。

    如果用户设法将插入符号移到空间的左侧,则可能无法工作。

        2
  •  121
  •   jacob sud0    6 年前

    斯威夫特4:


    子类 UITextField :

    // MyTextField.swift
    import UIKit
    
    protocol MyTextFieldDelegate {
        func textFieldDidDelete()
    }
    
    class MyTextField: UITextField {
    
        var myDelegate: MyTextFieldDelegate?
    
        override func deleteBackward() {
            super.deleteBackward()
            myDelegate?.textFieldDidDelete()
        }
    
    }
    

    实施:

    // ViewController.swift
    
    import UIKit
    
    class ViewController: UIViewController, MyTextFieldDelegate {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // initialize textField
            let input = MyTextField(frame: CGRect(x: 50, y: 50, width: 150, height: 40))
    
            // set viewController as "myDelegate"
            input.myDelegate = self
    
            // add textField to view
            view.addSubview(input)
    
            // focus the text field
            input.becomeFirstResponder()
        }
    
        func textFieldDidDelete() {
            print("delete")
        }
    
    }
    

    ObjultC:


    子类 输入框 :

    //Header
    //MyTextField.h
    
    //create delegate protocol
    @protocol MyTextFieldDelegate <NSObject>
    @optional
    - (void)textFieldDidDelete;
    @end
    
    @interface MyTextField : UITextField<UIKeyInput>
    
    //create "myDelegate"
    @property (nonatomic, assign) id<MyTextFieldDelegate> myDelegate;
    @end
    
    //Implementation
    #import "MyTextField.h"
    
    @implementation MyTextField
    
    - (void)deleteBackward {
        [super deleteBackward];
    
        if ([_myDelegate respondsToSelector:@selector(textFieldDidDelete)]){
            [_myDelegate textFieldDidDelete];
        }
    }
    
    @end
    

    现在只需添加 MyTextFieldDelegate 对你 UIViewController 设置你的 UITextFields My委托 self :

    //View Controller Header
    #import "MyTextField.h"
    
    //add "MyTextFieldDelegate" to you view controller
    @interface ViewController : UIViewController <MyTextFieldDelegate>
    @end
    
    //View Controller Implementation
    - (void)viewDidLoad {
        //initialize your text field
        MyTextField *input = 
         [[MyTextField alloc] initWithFrame:CGRectMake(0, 0, 70, 30)];
    
        //set your view controller as "myDelegate"
        input.myDelegate = self;
    
        //add your text field to the view
        [self.view addSubview:input];
    }
    
    //MyTextField Delegate
    - (void)textFieldDidDelete {
        NSLog(@"delete");
    }
    
        3
  •  37
  •   Community Egal    7 年前

    更新:参见 JacobCaraballo's answer 例如,重写 -[UITextField deleteBackward] .

    退房 UITextInput ,具体地说 UIKeyInput 有一个 deleteBackward delegate method 那个 总是 当按下Delete键时调用。如果您正在做一些简单的事情,那么您可以考虑只进行子类化。 UILabel 使其符合 UIKEY输入 协议,由 SimpleTextInput 而这 iPhone UIKeyInput Example . 注: UITEXT输入 及其亲属(包括 UIKEY输入 )仅在iOS 3.2及更高版本中提供。

        4
  •  31
  •   Jeffrey Loo    11 年前

    代码如下:

    @interface MyTextField : UITextField
    @end
    
    @implementation MyTextField
    
    - (void)deleteBackward
    {
        [super deleteBackward];
    
        //At here, you can handle backspace key pressed event even the text field is empty
    }
    
    @end
    

    最后,不要忘记将文本字段的自定义类属性更改为“mytextfield”

        5
  •  17
  •   Alex Cio    10 年前

    我找到了比 subclass 解决方案。即使有点奇怪,但它工作正常。

    - (BOOL)textView:(UITextView *)textView 
            shouldChangeTextInRange:(NSRange)range 
            replacementText:(NSString *)text
    {
        const char * _char = [text cStringUsingEncoding:NSUTF8StringEncoding];
        int isBackSpace = strcmp(_char, "\b");
    
        if (isBackSpace == -8) {
           // is backspace
        }
    
        return YES;
    }
    

    比较结果是-8有点奇怪。也许我会在某些方面出错 C Programming . 但这是正确的做法;)

        6
  •  17
  •   Ruud Visser    7 年前

    Swift实施:

    import UIKit
    
    protocol PinTexFieldDelegate : UITextFieldDelegate {
        func didPressBackspace(textField : PinTextField)
    }
    
    class PinTextField: UITextField {
    
        override func deleteBackward() {
            super.deleteBackward()
    
            // If conforming to our extension protocol
            if let pinDelegate = self.delegate as? PinTexFieldDelegate {
                pinDelegate.didPressBackspace(self)
            }
        }
    }
    
        7
  •  10
  •   Alex Cio    10 年前

    试试 delegate

    - (BOOL)textField:(UITextField *)textField 
            shouldChangeCharactersInRange:(NSRange)range 
            replacementString:(NSString *)string {
    

    然后检查 range.length == 1 在什么时候 backspace 被击中。

        8
  •  9
  •   Pritesh    6 年前

    请使用下面的代码它将帮助您检测键盘删除键,即使您的文本字段是空的。

    目的:

    - (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }

    Swift:

    func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
    
        9
  •  8
  •   Ben Call    9 年前

    尼古拉斯·阿尔瓦厄斯的回答帮助我解决了一个类似的问题。

    我将输入限制为特定的字符集,但它忽略了退格。 所以我查过了 range.length == 1 在修剪之前 NSString . 如果是真的,我就把绳子还给你,不要修剪它。见下文

     - (BOOL) textField:(UITextField *)textField 
              shouldChangeCharactersInRange:(NSRange)range 
              replacementString:(NSString *)string
     {
         NSCharacterSet *nonNumberSet = 
          [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] 
             invertedSet];
    
        if (range.length == 1) {
           return string;
        }
        else {
           return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0);
        }   
     }
    
        10
  •  5
  •   Himanshu padia Sachin Gurnani    7 年前

    是的,当textfield为空时,使用下面的方法检测退格。

    需要添加 UITextFieldDelegate

    yourtextfield.delegate=本人 (必须要求)

    Swift:

    func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { 
        return true
    }
    

    目的:

    - (BOOL)keyboardInputShouldDelete:(UITextField *)textField { 
        return YES; 
    }
    
        11
  •  4
  •   Community Egal    7 年前

    对于那些有问题的人 Jacob's answer 我实现了我的textfield子类如下,它工作得很好!

    #import <UIKit/UIKit.h>
    
    @class HTTextField;
    
    @protocol HTBackspaceDelegate <NSObject>
    
    @optional
    - (void)textFieldDidBackspace:(HTTextField*)textField;
    @end
    
    @interface HTTextField : UITextField<UIKeyInput>
    
    @property (nonatomic, assign) id<HTBackspaceDelegate> backspaceDelegate;
    
    @end
    
    
    #import "HTTextField.h"
    
    @implementation HTTextField
    
    - (void)deleteBackward {
        [super deleteBackward];
        if ([self.backspaceDelegate respondsToSelector:@selector(textFieldDidBackspace:)]){
            [self.backspaceDelegate textFieldDidBackspace:self];
        }
    }
    
    - (BOOL)keyboardInputShouldDelete:(UITextField *)textField {
        BOOL shouldDelete = YES;
    
        if ([UITextField instancesRespondToSelector:_cmd]) {
            BOOL (*keyboardInputShouldDelete)(id, SEL, UITextField *) = (BOOL (*)(id, SEL, UITextField *))[UITextField instanceMethodForSelector:_cmd];
    
            if (keyboardInputShouldDelete) {
                shouldDelete = keyboardInputShouldDelete(self, _cmd, textField);
            }
        }
    
        if (![textField.text length] && [[[UIDevice currentDevice] systemVersion] intValue] >= 8) {
            [self deleteBackward];
        }
    
        return shouldDelete;
    }
    
    @end
    
        12
  •  3
  •   Alex Cio    10 年前

    我发现检测退格的最佳用途是当用户在一个空的 UITextField . 例如,如果邮件应用程序中有“冒泡”收件人,则当您在 输入框 ,它选择最后一个“冒泡”收件人。

    这与雅各布·卡拉巴罗的回答类似。但在雅各布的回答中,如果 输入框 当您按退格键时,在收到委托消息时,还剩一个字符, 输入框 将已经是空的,因此您可以有效地检测 backspace 在最多包含一个字符的文本字段上。

    实际上,如果你想检测 退格 在A上 输入框 使用零个字符(空),则应将消息发送到 delegate 在呼叫之前 super deleteBackward . 例如:

    #import "MyTextField.h"
    
    //Text field that detects when backspace is hit with empty text
    @implementation MyTextField
    
    #pragma mark - UIKeyInput protocol
    -(void)deleteBackward
    {
      BOOL isTextFieldEmpty = (self.text.length == 0);
      if (isTextFieldEmpty) {
        if ([self.delegate 
             respondsToSelector:@selector(textFieldDidHitBackspaceWithEmptyText:)]) {
    
            [self.delegate textFieldDidHitBackspaceWithEmptyText:self];
            }
        }
        [super deleteBackward];
    }
    @end
    

    此类文本字段的界面如下所示:

    @protocol MyTextFieldDelegate;
    
    @interface MyTextField : UITextField
    @property(nonatomic, weak) id<MyTextFieldDelegate> delegate;
    @end
    
    @protocol MyTextFieldDelegate <UITextFieldDelegate>
    @optional
    -(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField;
    @end
    
        13
  •  2
  •   tracy    12 年前

    在iOS6中,当按下backspace时(包括当字段为空时),会在uitextfield上调用deleteBackward方法。因此,您可以对uitextfield进行子类化,并提供自己的deletebackward实现(也调用super的实现)。

    不过我仍然支持iOS5,所以我需要结合安德鲁的答案和这个。

        14
  •  1
  •   Alex Cio    10 年前

    :)仅用于标题“检测退格键”,我在这里使用 UIKeyboardTypeNumberPad .

    今晚我也遇到了同样的问题,我的代码是:

    - (BOOL)textField:(UITextField *)textField 
            shouldChangeCharactersInRange:(NSRange)range 
            replacementString:(NSString *)string
    {
        NSLog([NSString stringWithFormat:@"%d", [string length]]);
    }
    

    因为有 ui键盘类型数字键盘 ,用户只能输入数字或退格,所以当字符串长度为0时,必须是退格键。

    希望以上能有所帮助。

        15
  •  1
  •   Alex Cio    10 年前

    而不是试图预先构造文本字段中的内容,或找出在 shouldChangeCharactersInRange 方法,我建议执行以下操作:

    [self performSelector:@selector(manageSearchResultsDisplay) 
               withObject:nil 
               afterDelay:0];
    

    这允许您在当前操作完成后直接调用方法。最酷的是,当它完成时,修改后的值将已经在 UITextField . 在这一点上,您可以检查它的长度和/或根据存在的内容进行验证。

        16
  •  1
  •   joel.d    9 年前

    在iOS 8.3上,UItextfield子类化对我不起作用,从未调用过DeleteBackward。

    以下是我使用的解决方案,适用于所有iOS 8版本,也适用于其他iOS版本

    for textField in textFields {
                textField.text = " "
    }
    
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
            if string == "" && textField.text == " "   {
                // Do stuff here
                return false
            }
            return true
    }
    
        17
  •  1
  •   Midhul    6 年前

    在.h文件中添加uikeinput委托

    - (BOOL)keyboardInputShouldDelete:(UITextField *)textField {
    
    if ([textField isEqual:_txtFirstDigit]) {
    
    }else if([textField isEqual:_txtSecondDigit]) {
        [_txtFirstDigit becomeFirstResponder];
    
    }else if([textField isEqual:_txtThirdDigit]) {
        [_txtSecondDigit becomeFirstResponder];
    
    }else if([textField isEqual:_txtFourthDigit]) {
        [_txtThirdDigit becomeFirstResponder];
    }
    return YES;
    }   
    

    改进的格式

        18
  •  1
  •   Hemang    6 年前

    我已经实现了类似的解决方案,并做了一些小的改进,告诉我当用户点击退格键时,如果文本字段有任何值。如果按退格键时文本字段为空,则只应关注另一个文本字段,这对我的情况很有用。

    protocol MyTextFieldDelegate : UITextFieldDelegate {
        func textFieldDidDelete(textField: MyTextField, hasValue: Bool)
    }
    
    override func deleteBackward() {
        let currentText = self.text ?? ""
        super.deleteBackward()
        let hasValue = currentText.isEmpty ? false : true
        if let delegate = self.delegate as? MyTextFieldDelegate {
            delegate.textFieldDidDelete(textField: self, hasValue: hasValue)
        }
    }
    
        19
  •  1
  •   Tim    5 年前

    The most poplar answer 是否缺少一个功能,即检测文本字段是否为空。

    也就是说,当重写text field子类的deleteBackwards()方法时,仍然不知道文本字段是否已经为空。(在deleteBackwards()之前和之后, textField.text! 是空字符串: "" )

    这是我的改进,删除前检查一下是否有空。

    1。创建扩展UItextfieldDelegate的委托协议

    protocol MyTextFieldDelegate: UITextFieldDelegate {
        func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool)
    }
    

    2。UItextfield子类

    class MyTextField: UITextField {
        override func deleteBackward() {
            // see if text was empty
            let wasEmpty = text == nil || text! == ""
    
            // then perform normal behavior
            super.deleteBackward()
    
            // now, notify delegate (if existent)
            (delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
        }
    }
    

    三。实现新的委托协议

    extension MyViewController: MyTextFieldDelegate {
        func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
            if wasEmpty {
                // do what you want here...
            }
        }
    }
    
        20
  •  -2
  •   Bhumit Mehta    11 年前

    为了简单起见,这里是你需要检查的唯一条件

         if (range.length==1)
    
        21
  •  -2
  •   K-AnGaMa    10 年前
    + (BOOL)detectBackspaceOnly:(NSString *)string
    {
        for(int i=0 ; i<string.length ; i++){
            unichar caract = [string characterAtIndex:i];
            if(caract != ' ' && caract != '\n')
                return NO;
        }
    
        return YES;
    }
    
        22
  •  -2
  •   Alex Cio    10 年前

    像这样:

    - (BOOL)textField:(UITextField *)textField 
            shouldChangeCharactersInRange:(NSRange)range 
            replacementString:(NSString *)string       
    {  
        if (![text hash] && ![textField.text length])  
            [self backspaceInEmptyTextField];  
    }
    

    当然,哈希是针对一个字符串的。

        23
  •  -2
  •   izstas    10 年前

    使用textfield委托方法:

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    

    在上述方法中添加以下代码以检测删除事件

    if(textField == YourTextField)
    {
        if ([string length] == 0 && range.length > 0)
        {
            // Your Code after deletion of character
        }
    }
    
        24
  •  -4
  •   klefevre    9 年前

    UITextViewDelegate :

    - (BOOL)               textView:(UITextView *)textView 
            shouldChangeTextInRange:(NSRange)range 
                    replacementText:(NSString *)text
    {
        if(text isEqualToString:@"");
        {
            NSLog(@"press backspace.");
        }
    }
    

    它对我来说没问题。

    中文简体拼音和手写输入的更新:

    - (BOOL)               textView:(UITextView *)textView 
            shouldChangeTextInRange:(NSRange)range 
                    replacementText:(NSString *)text
    {
        if (range.length > 0 && [text isEqualToString:@""]) {
            NSLog(@"press Backspace.");
        }
        return YES;
    }
    

    根据文件显示:

    “如果用户按下 deleteKey ,范围的长度为1,空字符串对象替换该单个字符。“