检测UITextField中的退格事件

问题描述 投票:25回答:11

我正在寻找关于如何捕获退格事件的解决方案,大多数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;
}
ios swift cocoa-touch uikit uitextfielddelegate
11个回答
59
投票

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
投票

Swift 4:如果用户按下退格按钮,则字符串为空,因此此方法强制textField仅接受来自指定字符集(在本例中为utf8字符)和退格(string.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
    }
}

1
投票

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

18
投票

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

:)


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时,方法调配也应该没问题。


11
投票

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

  1. 创建隐形标志 private struct Constants { static let InvisibleSign = "\u{200B}" }
  2. 为textField设置委托 textField.delegate = self
  3. 在事件EditingChanged检查文本,如果需要添加隐形符号,如下所示: @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 } } }

enter image description here

  1. 添加委托方法textField:shouldChangeCharactersInRange:replacementString:的实现 extension UIViewController : UITextFieldDelegate { // MARK: - UITextFieldDelegate func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let char = string.cStringUsingEncoding(NSUTF8StringEncoding)! let isBackSpace = strcmp(char, "\\b") if (isBackSpace == -92) { if var string = textField.text { string = string.stringByReplacingOccurrencesOfString(Constants.InvisibleSign, withString: "") if string.characters.count == 1 { //last visible character, if needed u can skip replacement and detect once even in empty text field //for example u can switch to prev textField //do stuff here } } } return true } }

7
投票

试试这个

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

if(string == "") {

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

注意:如果要允许退格,可以返回“true”。否则你可以返回“假”。


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

4
投票

Swift 4

我发现使用strcmp无关的比较。我们甚至不知道strcmp是如何在引擎盖后面运行的。在比较当前char和\b的所有其他答案中,结果是目标C中的-8和Swift中的-92。我写了这个答案,因为上述解决方案对我不起作用。 (Xcode版本9.3 (9E145)使用Swift 4.1

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

PS:别忘了给你的delegates指定合适的textFields

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

    let  char = string.cString(using: String.Encoding.utf8)!
    if (char.elementsEqual([0])) {
        print("Backspace was pressed")
    }
    else {
        print("WHAT DOES THE FOX SAY ?\n")
        print(char)
    }
    return true
}

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
}

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

© www.soinside.com 2019 - 2024. All rights reserved.