即使UITextField为空,我还能检测到删除键吗?

时间:2011-05-11 02:26:14

标签: iphone ios uitextfield

当UITextField什么都不包含时,按下键盘的删除键不会调用任何UITextFieldDelegate的方法。

我如何检测它?

编辑: 似乎没有什么简单的方法可以做到这一点。我能找到的最有用的链接是:

  1. UITextField : Any way to detect the Delete key event when the field is empty ?

  2. How to get the actual key pressed in a UITextField

  3. 简而言之,我的解决方案是在文本字段的开头放置一个永久的SPACE。并进行其他必要的更改(textFieldShouldReturn:,textField:shouldChangeCharactersInRange:replacementString:,etc。)。

9 个答案:

答案 0 :(得分:8)

这似乎可以通过继承UITextField来实现。 UITextField符合名为UITextInput的协议,该协议符合另一个名为UIKeyInput的协议。 UIKeyInput协议有一个方法deleteBackward,每次按下键盘上的退格键时都会触发。

以下是它的外观

标题

#import <UIKit/UIKit.h>

@interface EmptyDeleteTextField : UITextField

@end

<强>实施

- (void)deleteBackward
{
    NSLog_SM(@"Length: %d", (int)self.text.length);
    [super deleteBackward];
}

PS:不要忘记打电话给super,因为你不想搞乱UITextField的默认行为。

答案 1 :(得分:5)

我在swift 3中添加了这个答案以获得更完整的示例。 基本上,我需要一个密码类型视图,其中我有多个文本字段,每个单元格中允许一个字符。

像这样 enter image description here 我首先创建了一个UITextField的子类和一个定义新函数的协议。

protocol MYDeleteActionTextFieldDelegate {
    func textFieldDidSelectDeleteButton(_ textField: UITextField) -> Void
}
class MYDeleteActionTextField: UITextField {
    var deleteDelegate: MYDeleteActionTextFieldDelegate?
    override func deleteBackward() {
        // Need to call this before super or the textfield edit may already be in place
        self.deleteDelegate?.textFieldDidSelectDeleteButton(self)
        super.deleteBackward()
    }
}

然后使用新的子类创建文本字段,并在视图控制器中实现委托。在我的例子中,我管理数组中的文本字段以便于使用,并使用PureLayout布局单元格。我像这样存储它们

var pinFields = UITextField

然后在viewDidLoad()中,我将所有引脚字段添加到数组中,如下所示:

for _ in 1...6 {
            let field = EDFDeleteActionTextField.init(forAutoLayout: ())
            field.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
            field.delegate = self
            field.deleteDelegate = self
            field.textAlignment = .center
            field.font = UIFont.newBigTitle()
            field.textColor = UIColor.edfBlue()
            field.backgroundColor = UIColor.edfWhite()
            self.pinFields.append(field)
            self.pinView.addSubview(field)
        }

现在您只需要回复所有适当的委托方法和上面添加的textFieldDidChange目标。

// MARK: UITextFieldDelegate
    func textFieldDidChange(textField: UITextField) {
        // If the user typed one character, move to the next cell.
        if (textField.text?.characters.count == 1) {
            let index = pinFields.index(of: textField)
            textField.resignFirstResponder()
            if (pinFields.count > index! + 1) {
                pinFields[index! + 1].becomeFirstResponder()
            }
        } // If they deleted the character move to previous cell
        else if (textField.text?.characters.count == 0) {
            let index = pinFields.index(of: textField)
            if (index! - 1 >= 0) {
                pinFields[index! - 1].becomeFirstResponder()
            }
        }
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if range.location > 0 {
            let index = pinFields.index(of: textField)
            // If there is already text in the text field and the next cell is empty - move the newly typed character to that cell.
            if (pinFields.count > index! + 1) {
                let nextField = pinFields[index! + 1]
                if (nextField.text?.characters.count == 0) {
                    textField.resignFirstResponder()
                    nextField.becomeFirstResponder()
                    nextField.text = string
                }
            }
            return false
        }
        return true
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return false
    }

    // MARK: EDFDeleteActionTextFieldDelegate
    func textFieldDidSelectDeleteButton(_ textField: UITextField) {
        // If user clicked delete, and there are no characters, move to previous cell if available.
        // If there are characters, it is handled in UITextFieldDelegate
        if (textField.text?.characters.count == 0) {
            let index = pinFields.index(of: textField)
            if (index! - 1 >= 0) {
                pinFields[index! - 1].becomeFirstResponder()
            }
            else {
                textField.resignFirstResponder()
            }
        }
    }

我将省略枯燥的部分(比如布置文本字段等),因为这个一般功能在比这个密码视图更多的情况下是有用的,但实现这个子类和协议应该提供你需要的所有功能对于类似的类型视图并解决手头的问题(这可能需要类似的东西)。

快乐的编码。

答案 2 :(得分:4)

好的,我已经明白了。所以在 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text 委托方法(即当文本即将被输入时)你只需要做一个

if (text.length <= 0) {
    // backspace
    return FALSE;
} else {

因为对于退格键text.length将== 0,其他所有内容将== 1。

答案 3 :(得分:4)

这可以通过继承UITextField并将其添加为所需文本字段的自定义类来实现。 然后覆盖方法“deleteBackward” 此方法将捕获所有退格事件。

Swift中的代码:

override func deleteBackward() {
        super.deleteBackward()
        // Enter your stuff here
    }

同时确保你也在调用super方法,因为它正在执行事件的基本功能。

答案 4 :(得分:1)

在上面放一个隐形按钮。

答案 5 :(得分:1)

可以在它上面放一个按钮,但这有点脆弱,因为键盘布局可能会随着不同的iOS版本而改变,并且肯定会有不同语言的不同键盘布局。

查看“管理文本字段和文本视图”Apple文档。我确定有办法做到这一点。它类似于UITextField实现了一个获取keyevents的协议。其中一个关键事件可能是删除键,因此您可以覆盖接收这些键的任何方法并以此方式获取。

答案 6 :(得分:1)

我不确定,但您可以尝试使用addTarget: action: forControlEvents:的自定义方法吗?试试UIControlEventAllEditingEvents选项。

答案 7 :(得分:0)

对于Q1。

下面的Swift 4.2对我有用

@objc func keyboardInputShouldDelete(_ textField: UITextField) -> Bool {
        print("User Pressed backspace in empty textfield ")
        return true
    }

答案 8 :(得分:-1)

使用键盘时,显然你正在将它写入某个变量(例如:UITextField,UILabel甚至是全局字符串)

检测删除操作的选项可以是:

  • 保持全局“int previousLengthOfText”
  • 将此var设为lastLengthOfText = 0;
  • 捕获委托功能的变化:例如:

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

  • 将标签\ textField的长度与此全局变量进行比较,并查看是否添加或删除了字符。

例如:

if ([self.myTextField.text length] > previousLengthOfText) {
{
// user deleted a character - Do your action here
previousLengthOfText = [self.myTextField.text length];
}