检测UITextField中的退格事件

Wan*_*ery 30 cocoa-touch uikit ios uitextfielddelegate swift

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

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

self.textField.delegate = self;
Run Code Online (Sandbox Code Playgroud)

然后我知道使用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;
}
Run Code Online (Sandbox Code Playgroud)

Lon*_*ham 67

希望能帮到你:p

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
}
Run Code Online (Sandbox Code Playgroud)

  • 除非textField不为空,否则这很有用 (16认同)
  • -1:这段代码有效,但不小心.[文档](https://developer.apple.com/documentation/uikit/uitextfielddelegate/1619599-textfield)指定如果用户删除一个或多个字符,`string`将为空字符串. (4认同)
  • 这个答案是危险的错误,应该避免。strcmp 的具体返回值(除了它的符号)是没有意义的。字符串是空的,不是`\b`。 (3认同)
  • @gbk 检查此链接 /sf/ask/138455411/ 以检测退格,即使 TextField 为空。 (2认同)

Ort*_*ntz 19

我更喜欢子类化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()
    }
}
Run Code Online (Sandbox Code Playgroud)

shouldChangeCharactersInRange黑客与被放置在文本字段中有不可见字符组合有几个缺点:

  • 如果连接了键盘,可以将光标放在不可见的字符之前,并且不再检测到退格,
  • 用户甚至可以选择那个不可见的角色(Shift Arrow在键盘上使用,甚至通过点击插入符号)并且会对这个奇怪的角色感到困惑,
  • 只要只有这个看不见的角色,自动完成栏就会提供奇怪的选择,
  • placeholder不再被示出,
  • 即使它不应该显示清除按钮clearButtonMode = .whileEditing.

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

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

  • 谢谢!这么多多余的答案都没有回答这个问题但你的正确答案就在这里:) (2认同)

Ins*_*sou 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
}
Run Code Online (Sandbox Code Playgroud)

:)


gbk*_*gbk 11

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

  1. 创建隐形标志

    private struct Constants {
        static let InvisibleSign = "\u{200B}"
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 为textField设置委托

    textField.delegate = self
    
    Run Code Online (Sandbox Code Playgroud)
  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
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  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
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)


Aug*_*P A 7

试试这个

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

if(string == "") {

        print("Backspace pressed");
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:如果要允许退格,可以返回" true ".否则你可以返回" ".

  • `string ==""`而不是更好地使用`.isEmpty` (3认同)

Dmi*_*lov 7

请不要乱码。只需将此扩展名放在代码中的某个位置即可。

斯威夫特5.1

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

然后在您的函数中使用它

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


Rom*_*nko 7

我实现了这个功能:

在此处输入图片说明

而在最后一个 textFiled 为空的情况下,我只想切换到上一个 textFiled。我尝试了上面的所有答案,但没有一个在我的情况下工作正常。出于某种原因,如果我不是增加更多的逻辑printisBackSpace == -92括号阻止这种方法刚刚停止工作...

至于我,下面的方法更优雅,而且效果很好:

迅速

class YourTextField: UITextField {

    // MARK: Life cycle

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

    // MARK: Methods

    override func deleteBackward() {
        super.deleteBackward()

        print("deleteBackward")
    }

}
Run Code Online (Sandbox Code Playgroud)

感谢@LombaX 的回答


Amr*_*gry 5

斯威夫特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
            }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

雨燕4

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

仅供参考:您实际键入的每个字符都是一个1或多个元素的数组utf8 Encoding。退格字符是[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
}
Run Code Online (Sandbox Code Playgroud)