检测UITextField中的退格事件

时间:2015-04-08 01:25:03

标签: ios swift cocoa-touch uikit uitextfielddelegate

我正在寻找有关如何捕获退格事件的解决方案,大多数Stack Overflow答案都在Objective-C中,但我需要使用Swift语言。

首先,我为UITextField设置了委托并将其设置为self

self.textField.delegate = self;

然后我知道使用shouldChangeCharactersInRange委托方法来检测是否按下退格是所有代码都在Objective-C中。我需要在Swift中使用以下方法,如下所示。

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    const char * _char = [string cStringUsingEncoding:NSUTF8StringEncoding];
    int isBackSpace = strcmp(_char, "\b");

    if (isBackSpace == -8) {
        // NSLog(@"Backspace was pressed");
    }

    return YES;
}

12 个答案:

答案 0 :(得分:57)

Swift 4.2

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    if let char = string.cString(using: String.Encoding.utf8) {
        let isBackSpace = strcmp(char, "\\b")
        if (isBackSpace == -92) {
            print("Backspace was pressed")
        }
    }
    return true
}

较旧的Swift版

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let  char = string.cStringUsingEncoding(NSUTF8StringEncoding)!
    let isBackSpace = strcmp(char, "\\b")

    if (isBackSpace == -92) {
        println("Backspace was pressed")
    }
    return true
}

答案 1 :(得分:16)

在Swift 3中

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let  char = string.cString(using: String.Encoding.utf8)!
    let isBackSpace = strcmp(char, "\\b")

    if (isBackSpace == -92) {
         print("Backspace was pressed")
    }
    return true
}

:)

答案 2 :(得分:15)

我更喜欢继承UITextField并覆盖deleteBackward(),因为这比使用shouldChangeCharactersInRange的黑客更可靠:

class MyTextField: UITextField {
    override public func deleteBackward() {
        if text == "" {
             // do something when backspace is tapped/entered in an empty text field
        }
        // do something for every backspace
        super.deleteBackward()
    }
}

shouldChangeCharactersInRange hack与文本字段中放置的不可见字符相结合有几个缺点:

  • 连接了键盘,可以将光标放在不可见的字符之前,并且不再检测到退格,
  • 用户甚至可以选择那个不可见的角色(在键盘上使用Shift Arrow,或者甚至通过点击插入符号)并且会对这个奇怪的角色感到困惑,
  • 自动完成栏提供了奇怪的选择,只要只有这个不可见的字符,
  • 具有基于文本字段文本的候选选项的亚洲语言键盘将会混淆,
  • placeholder已不再显示,
  • 即使clearButtonMode = .whileEditing不应该显示清除按钮。

当然,由于需要子类化,覆盖deleteBackward()有点不方便。但更好的用户体验值得付出努力!

如果子类化是不合法的,例如当UISearchBar使用嵌入式UITextField时,方法调整也应该没问题。

答案 3 :(得分:11)

如果你需要在空textField中检测退格(例如,如果你需要在backSpace按下时自动切换回prev textField),你可以使用建议方法的组合 - 添加隐形符号并使用标准委托方法{{1喜欢关注

  1. 创建隐形标志

    textField:shouldChangeCharactersInRange:replacementString:
  2. 设置textField的委托

    private struct Constants {
        static let InvisibleSign = "\u{200B}"
    }
    
  3. 在事件textField.delegate = self 上检查文字,如果需要,请添加隐身符号,如下所示:

    EditingChanged
  4. enter image description here

    1. 添加委托方法@IBAction func didChangeEditingInTextField(sender: UITextField) { if var text = sender.text { if text.characters.count == 1 && text != Constants.InvisibleSign { text = Constants.InvisibleSign.stringByAppendingString(text) sender.text = text } } }

      的实现
      textField:shouldChangeCharactersInRange:replacementString:

答案 4 :(得分:7)

试试这个

public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {

if(string == "") {

        print("Backspace pressed");
        return true;
    }
}

注意:您可以返回" true "如果你想允许退格。否则,您可以返回" false "。

答案 5 :(得分:5)

Swift 4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

            let  char = string.cString(using: String.Encoding.utf8)!
            let isBackSpace = strcmp(char, "\\b")

            if isBackSpace == -92 {
                print("Backspace was pressed")
                return false
            }
}

答案 6 :(得分:4)

Swift 4

我发现使用strcmp无关的比较。我们甚至不知道strcmp是如何在幕后操作的。在比较当前字符和\b结果的所有其他答案中,{C} -8在{C}和{{1}在Swift中。我写了这个答案,因为上述解决方案对我不起作用。 (Xcode版本-92使用Swift 9.3 (9E145)

仅供参考:您实际输入的每个字符都是4.11或更多元素的数组。 backSpace字符为utf8 Encoding。你可以尝试一下。

PS:请勿忘记为[0]分配正确的delegates

textFields

答案 7 :(得分:3)

请不要丢弃您的代码。只需将此扩展名放在代码中的某处即可。 (斯威夫特4.1)

extension String {
  var isBackspace: Bool {
    let char = self.cString(using: String.Encoding.utf8)!
    return strcmp(char, "\\b") == -92
  }
}

然后在你的函数中使用它

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
  if string.isBackspace {
    // do something
  }
  return true
}

答案 8 :(得分:3)

我实现了此功能:

enter image description here

在最后一个textFiled为空的情况下,我只想切换到上一个textFiled。我尝试了以上所有答案,但在我的情况下没有人能正常工作。由于某些原因,如果我在print括号中添加的逻辑多于isBackSpace == -92,则此方法就停止了工作...

对于我来说,下面的方法更优雅,更像是一种魅力:

快速

class YourTextField: UITextField {

    // MARK: Life cycle

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    // MARK: Methods

    override func deleteBackward() {
        super.deleteBackward()

        print("deleteBackward")
    }

}

感谢@LombaX提供answer

答案 9 :(得分:1)

Swift 4:如果用户按下退格按钮,则字符串为空,因此此方法强制textField仅接受来自指定字符集(在本例中为utf8字符)和退格(字符串)的字符。 isEmpty case)。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if string.cString(using: String.Encoding.utf8) != nil {
        return true
    } else if string.isEmpty {
        return true
    } else {
        return false
    }
}

答案 10 :(得分:1)

Swift 4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    //MARK:- If Delete button click
    let  char = string.cString(using: String.Encoding.utf8)!
    let isBackSpace = strcmp(char, "\\b")

    if (isBackSpace == -92) {
        print("Backspace was pressed")

        return true
    }
}

答案 11 :(得分:0)

Swift 5: 根据文本视图委托 documentation,如果 shouldChangeTextIn 方法返回的替换文本为空,则用户按下退格按钮。如果范围上限大于范围下限(或范围计数为 1 或更多),则应删除文本。如果范围上限和下限相同(或都等于 0),则没有要删除的文本(长度为 0 的范围将被替换为空)。我测试过,即使在空文本字段上也会调用它。

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    
    guard text.isEmpty else { return true } // No backspace pressed
    if (range.upperBound > range.lowerBound) {
        print("Backspace pressed")
    } else if (range.upperBound == range.lowerBound) {
        print("Backspace pressed but no text to delete")
        if (textView.text.isEmpty) || (textView.text == nil) {
            print("Text view is empty")
        }
    }
    return true
}