Detect backspace Event in UITextField

后端 未结 11 566
自闭症患者
自闭症患者 2020-12-04 16:35

I am searching for solutions on how to capture a backspace event, most Stack Overflow answers are in Objective-C but I need on Swift language.

First I have set deleg

相关标签:
11条回答
  • 2020-12-04 17:07

    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
                }
    }
    
    0 讨论(0)
  • 2020-12-04 17:09

    I implemented this feature:

    And in the case where the last textFiled is empty, I just want to switch to the previous textFiled. I tried all of the answers above, but no one works fine in my situation. For some reason, if I add more logic than print in isBackSpace == -92 parentheses block this method just stopped work...

    As for me the method below more elegant and works like a charm:

    Swift

    class YourTextField: UITextField {
    
        // MARK: Life cycle
    
        override func awakeFromNib() {
            super.awakeFromNib()
        }
    
        // MARK: Methods
    
        override func deleteBackward() {
            super.deleteBackward()
    
            print("deleteBackward")
        }
    
    }
    

    Thanks @LombaX for the answer

    0 讨论(0)
  • 2020-12-04 17:16

    I prefer subclassing UITextField and overriding deleteBackward() because that is much more reliable than the hack of using 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()
        }
    }
    

    The shouldChangeCharactersInRange hack combined with an invisible character that is placed in the text field has several disadvantages:

    • with a keyboard attached, one can place the cursor before the invisible character and the backspace isn't detected anymore,
    • the user can even select that invisible character (using Shift Arrow on a keyboard or even by tapping on the caret) and will be confused about that weird character,
    • the autocomplete bar offers weird choices as long as there's only this invisible character,
    • Asian language keyboards that have candidate options based on the text field's text will be confused,
    • the placeholder isn't shown anymore,
    • the clear button is displayed even when it shouldn't for clearButtonMode = .whileEditing.

    Of course, overriding deleteBackward() is a bit inconvenient due to the need of subclassing. But the better UX makes it worth the effort!

    And if subclassing is a no-go, e.g. when using UISearchBar with its embedded UITextField, method swizzling should be fine, too.

    0 讨论(0)
  • 2020-12-04 17:16

    Swift 4

    I find the comparison using strcmp irrelevant. We don't even know how strcmp is operating behind the hoods.In all the other answers when comparing current char and \b results are -8 in objective-C and -92 in Swift. I wrote this answer because the above solutions did not work for me. ( Xcode Version 9.3 (9E145) using Swift 4.1 )

    FYI : Every character that you actually type is an array of 1 or more elements in utf8 Encoding. backSpace Character is [0]. You can try this out.

    PS : Don't forget to assign the proper delegates to your 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
    }
    
    0 讨论(0)
  • 2020-12-04 17:19

    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
    }
    

    Older Swift version

    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
    }
    
    0 讨论(0)
  • 2020-12-04 17:22

    If u need detect backspace even in empty textField (for example in case if u need auto switch back to prev textField on backSpace pressing), u can use combination of proposed methods - add invisible sign and use standard delegate method textField:shouldChangeCharactersInRange:replacementString: like follow

    1. Create invisible sign

      private struct Constants {
          static let InvisibleSign = "\u{200B}"
      }
      
    2. Set delegate for textField

      textField.delegate = self
      
    3. On event EditingChanged check text and if needed add invisible symbol like follow:

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

    1. Add implementation of delegate method 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
          }
      }
      
    0 讨论(0)
提交回复
热议问题