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

问题描述 投票:0回答:10

当 UITextField 不包含任何内容时,按键盘的删除键不会调用 UITextFieldDelegate 的任何方法。

如何检测?

iphone ios uitextfield
10个回答
12
投票

我需要在 Swift 3 中使用 pincode 类型视图,其中有多个文本字段,每个单元格中允许一个字符。

像这样:

我首先创建 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()
            }
        }
    }

我将省略无聊的部分(例如布置文本字段等),因为这种通用功能在比此 pincode 视图更多的情况下有用,但实现此子类和协议应该提供类似功能所需的所有功能输入视图并解决手头的问题(可能需要类似的东西)。


9
投票

这似乎可以通过子类化 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 的默认行为。


8
投票

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

Swift 代码:

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

还要确保您也调用超级方法,因为它正在执行事件的基本功能。


4
投票

好吧,我已经弄清楚了。所以在

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
委托方法(即当即将输入文本时)您只需执行 a

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

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


1
投票

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

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


1
投票

我不确定,但您可以使用

addTarget: action: forControlEvents:
尝试自定义方法吗?尝试使用
UIControlEventAllEditingEvents
选项。


0
投票

在其上放置一个隐形按钮。


0
投票

对于第一季度。

在下面的 Swift 4.2 中对我有用

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

0
投票

将OP的解决方案从问题迁移到答案:

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

  1. UITextField:当字段为空时有什么方法可以检测删除键事件?

  2. 如何获取 UITextField 中按下的实际按键

简而言之,我的解决方案是在文本字段的开头放置一个永久的空格。并进行其他必要的更改(

textFieldShouldReturn:
textField:shouldChangeCharactersInRange:replacementString:
等)。


-1
投票

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

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

  • 保留全局“int previousLengthOfText”
  • 将此变量初始化为
    lastLengthOfText = 0;
  • 捕捉委托函数的变化:例如:

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

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

例如:

if ([self.myTextField.text length] > previousLengthOfText) {
{
// user deleted a character - Do your action here
previousLengthOfText = [self.myTextField.text length];
}
© www.soinside.com 2019 - 2024. All rights reserved.