检测空UITextField中的退格

时间:2009-12-30 01:21:18

标签: ios iphone uitextfield backspace

有没有办法检测何时在UITextField的iPhone键盘上按下 Backspace / 删除键是否为空?我想知道只有当UITextField为空时才按下 Backspace


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

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

收到此通知(调用handleTextFieldChanged函数),但在空字段中按 Backspace 键时仍然不会。有什么想法吗?


这个问题似乎有些混乱。我想在按下 Backspace 键时收到通知。而已。但是,当UITextField已经为空时,解决方案也必须正常工作。

28 个答案:

答案 0 :(得分:131)

斯威夫特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")
    }

}

目标C:


子类UITextField

//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 myDelegate 设置为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");
}

答案 1 :(得分:40)

更新:有关覆盖-[UITextField deleteBackward]的示例,请参阅JacobCaraballo's answer

结帐UITextInput,特别是UIKeyInput有一个deleteBackward delegate method,当按下删除键时,总是被调用。如果您正在做一些简单的事情,那么您可以考虑仅对UILabel进行子类化并使其符合UIKeyInput协议,如SimpleTextInput和此iPhone UIKeyInput Example所做的那样。 注意:UITextInput及其亲属(包括UIKeyInput)仅适用于iOS 3.2及更高版本。

答案 2 :(得分:34)

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

如果用户设法将插入符号移动到空格的左侧,则可能无效。

答案 3 :(得分:31)

代码如下:

@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”

答案 4 :(得分:17)

快速实施:

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)
        }
    }
}

答案 5 :(得分:17)

我创建的其他方式比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 :(得分:10)

尝试delegate

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

然后检查点击range.length == 1backspace是否属于{{1}}。

答案 7 :(得分:10)

请使用以下代码,即使文本字段为空,也可以帮助您检测键盘删除键。

目标C:

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

斯威夫特:

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

答案 8 :(得分:8)

Niklas Alvaeus的回答帮助我解决了类似的问题

我限制了对特定字符集的输入,但它忽略了退格。 所以我在修剪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);
    }   
 }

答案 9 :(得分:5)

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

需要添加 UITextFieldDelegate

yourTextField.delegate = self (必须)

<强>夫特:

.mpeg

目标C:

.

答案 10 :(得分:4)

对于那些对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

答案 11 :(得分:3)

我发现用于检测退格的最佳用途是检测用户何时在空UITextField中按下退格键。例如,如果您在邮件应用中有“冒泡”的收件人,当您点击UITextField中的退格键时,它会选择最后一个“冒泡”的收件人。

这可以通过与Jacob Caraballo的答案类似的方式完成。但是在雅各布的回答中,如果UITextField在你回击空格时还剩下一个字符,那么当收到委托邮件时,UITextField已经是空的,所以你有效地检测到了{{1}在一个最多只有一个字符的文本字段上。

实际上,如果您想在backspace上检测到backspace,其中包含完全为零的字符(空),那么您应该在调用{{1}之前将消息发送到UITextField }}。例如:

delegate

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

super deleteBackward

答案 12 :(得分:2)

在iOS 6中,当按下退格键时,在UITextField上调用deleteBackward方法,包括字段为空时。所以你可以继承UITextField并提供你自己的deleteBackward实现(也可以调用super)。

我仍然支持iOS 5,所以我需要安德鲁的回答和这个的结合。

答案 13 :(得分:1)

我建议您不要试图预先构建文本字段中的Will BE OF或在shouldChangeCharactersInRange方法中输入特殊字符,我建议您执行以下操作:

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

这允许您在当前操作完成后直接调用方法。这有什么好处,到它完成时,修改后的值已经在UITextField。此时,您可以根据其中的内容检查其长度和/或进行验证。

答案 14 :(得分:1)

:)仅用于标题“检测退格”,我使用UIKeyboardTypeNumberPad

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

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

因为使用UIKeyboardTypeNumberPad,用户只能输入Number或backspace,所以当string的长度为0时,它必须是退格键。

希望以上会有所帮助。

答案 15 :(得分:1)

The most poplar answer缺少一件事-能够检测文本字段是否为空的功能。

也就是说,当您重写TextField子类的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)
    }
}

3。实施新的委托协议

extension MyViewController: MyTextFieldDelegate {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
        if wasEmpty {
            // do what you want here...
        }
    }
}

答案 16 :(得分:1)

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

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)
    }
}

答案 17 :(得分:1)

UITextField的子类化在iOS 8.3上对我不起作用,从未调用过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
}

答案 18 :(得分:1)

在.h文件中添加UIKeyInput委托

- (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;
}   

改进格式

答案 19 :(得分:0)

这是我基于@andrew想法的解决方案:

某处,例如在viewDidLoad中

Name    Surname TYPE
John    Greer   A
David   bear    A
Rose    beer    B
Tara    tea     B
Sam     Mac     B
Alan    Glass   B
Brad    Newman  A
Kristen Goodman A
Jessica Goodwin A
Heather Poker   B

然后

        textField.delegate = self
        textField.addTarget(self, action: #selector(valueChanged(_:)), for: .editingDidBegin)

答案 20 :(得分:0)

Swift 5.1 的具有单个数字的文本字段的综合处理程序:

  • 假定您具有textField的出口集合(也具有连接的委托)

1步

xxx

2步

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

final class MyTextField: UITextField {

    weak var myDelegate: MyTextFieldDelegate?

    override func deleteBackward() {
        let wasEmpty = text == nil || text == ""

        // then perform normal behavior
        super.deleteBackward()

        // now, notify delegate (if existent)
        (delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
    }
}

3步

final class ViewController: UIViewController {

    @IBOutlet private var textFields: [MyTextField]!

    override func viewDidLoad() {
        super.viewDidLoad()
        textFields.forEach {
            $0.delegate = self
            $0.myDelegate = self
        }
    }
}

答案 21 :(得分:0)

所有的答案都非常有帮助,我不知道为什么每个人都走协议路线。你可以用更少的代码和回调函数来做到这一点 -

Swift 5.0 或更高版本

  1. 制作一个扩展 UITextField 的自定义文本字段类并覆盖 deleteBackward 函数-

    class CustomTextField: UITextField {

    [<td align="center" width="2%">
    <b>SNo.</b>
    </td>, <td align="center">
    <b>District Name</b>
    </td>, <td align="center">
    <b>Block Name</b>
    </td>, <td align="center">
    <b>Panchayat Name</b>
    </td>, <td align="center">
    <b>Work Start Fin Year</b>
    </td>, <td align="center">
    <b>Work Status</b>
    </td>, <td align="center">
    <b>Work Code</b>
    </td>, <td align="center">
    <b>Work Name</b>
    </td>, <td align="center">
    <b>Master Work Category Name </b>
    </td>, <td align="center">
    <b>Work Category Name </b>
    </td>]
    
    

    }

  2. 假设您想根据 ViewController var backButtonPressedInEmptyTextField: (()->())? override func deleteBackward() { super.deleteBackward() if let text = self.text, text.count == 0{ backButtonPressedInEmptyTextField?() print("Back space clicked when textfield is empty") } } 中的内容执行某些操作。因此,在 MyViewController 中,只需执行以下操作-

    类 MyViewController:UIViewController{ @IBOutlet 弱 var sampleTextField: CustomTextField!{ 已设置{ sampleTextField.backButtonPressedInEmptyTextField = 返回按钮按下() } }

    MyViewController

    }

我觉得用闭包或者回调函数,干净多了。

答案 22 :(得分:-1)

您可以检查文本视图/字段的文本以查看其是否为空,并确保在shouldChangeTextIn委托方法中替换文本也为空。

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if (textView.text == "" && text == "") {
        print("Backspace on empty text field.")
    }
    return true
}

答案 23 :(得分:-2)

使用TextField Delegate方法:

- (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 :(得分:-2)

+ (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;
}

答案 25 :(得分:-2)

要保持简单,这是您需要检查的唯一条件

     if (range.length==1)

答案 26 :(得分:-2)

这样的事情:

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

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

答案 27 :(得分:-4)

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,空字符串对象将替换该单个字符。”