Swift 4:UITextField成为第一响应者时如何检测删除键按下?空文本场景怎么办?
shouldChangeCharactersInRange When Empty Got it, this is a super common gotcha when working with UITextField—I’ve run into this exact issue before! The problem happens because the system doesn’t call shouldChangeCharactersInRange when there are no characters left to modify. Here are two solid solutions to handle this scenario:
Solution 1: Subclass UITextField and Override deleteBackward()
This is the most straightforward and reusable approach. By creating a custom UITextField subclass, you can intercept the delete key press directly, even when the field is empty.
Step 1: Create the Custom TextField
class CustomDeleteTextField: UITextField { override func deleteBackward() { // First run the default delete behavior super.deleteBackward() // Check if the field is empty (either before or after deletion) let isEmpty = text?.isEmpty ?? true if isEmpty { // Notify your delegate or run your custom logic here if let customDelegate = delegate as? CustomTextFieldDelegate { customDelegate.textFieldDidTapDeleteWhenEmpty(self) } } } } // Define a custom delegate protocol to handle the empty delete event protocol CustomTextFieldDelegate: UITextFieldDelegate { func textFieldDidTapDeleteWhenEmpty(_ textField: UITextField) }
Step 2: Use the Custom TextField in Your View Controller
class YourViewController: UIViewController, CustomTextFieldDelegate { override func viewDidLoad() { super.viewDidLoad() let textField = CustomDeleteTextField(frame: CGRect(x: 20, y: 100, width: 300, height: 40)) textField.borderStyle = .roundedRect textField.delegate = self view.addSubview(textField) } // Implement the custom delegate method func textFieldDidTapDeleteWhenEmpty(_ textField: UITextField) { // Your logic for handling delete key on empty field goes here print("Delete key pressed while text field is empty!") } // Keep your existing shouldChangeCharactersInRange implementation func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // Your original logic here return true } }
Solution 2: Track Text Changes with editingChanged Event (No Subclassing)
If you don’t want to subclass UITextField, you can use a combination of the editingChanged control event and tracking the previous text value to detect when the delete key is pressed on an empty field.
class YourViewController: UIViewController, UITextFieldDelegate { private var previousTextFieldText: String = "" override func viewDidLoad() { super.viewDidLoad() let textField = UITextField(frame: CGRect(x: 20, y: 100, width: 300, height: 40)) textField.borderStyle = .roundedRect textField.delegate = self // Add listener for editing changes textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) view.addSubview(textField) } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { // Save the current text before any changes previousTextFieldText = textField.text ?? "" return true } @objc private func textFieldDidChange(_ textField: UITextField) { let currentText = textField.text ?? "" // If both previous and current text are empty, delete key was pressed on empty field if currentText.isEmpty && previousTextFieldText.isEmpty { // Your custom logic here print("Delete key tapped on empty text field!") } // Update previous text for next time previousTextFieldText = currentText } }
Which Solution to Choose?
- Use Solution 1 if you need this behavior across multiple text fields in your app—it’s clean and reusable.
- Use Solution 2 for one-off cases where subclassing feels like overkill.
内容的提问来源于stack exchange,提问作者yancaico

