Обнаружение события backspace в UITextField
Я ищу решения о том, как захватить событие backspace, большинство ответов на переполнение стека находятся в 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;
}
Ответы
Ответ 1
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
}
Ответ 2
В 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
}
:)
Ответ 3
Я предпочитаю UITextField
подклассы UITextField
и переопределять deleteBackward()
потому что это гораздо более надежно, чем shouldChangeCharactersInRange
использования 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
сочетании с невидимым символом, помещаемым в текстовое поле, имеет несколько недостатков:
- при подключенной клавиатуре можно поместить курсор перед невидимым символом, и клавиша возврата больше не определяется,
- пользователь может даже выбрать этот невидимый символ (используя
Shift Arrow
на клавиатуре или даже нажав на каретку) и будет смущен этим странным персонажем, - панель автозаполнения предлагает странные варианты, пока есть только этот невидимый символ,
- Клавиатуры азиатского языка, которые имеют варианты кандидатов на основе текста текстового поля, будут сбиты с толку,
-
placeholder
больше не отображается, - кнопка очистки отображается, даже если для
clearButtonMode =.whileEditing
это не clearButtonMode =.whileEditing
.
Конечно, переопределение deleteBackward()
немного неудобно из-за необходимости создания подклассов. Но лучший UX стоит того!
И если создание подклассов не допускается, например, при использовании UISearchBar
со встроенным UITextField
, метод swizzling тоже должен быть в порядке.
Ответ 4
Если вам нужно обнаружить обратное пространство даже в пустом текстовом поле (например, если вам нужно автоматически переключиться обратно на предыдущий текстField на нажатие на backSpace), вы можете использовать комбинацию предлагаемых методов - добавить невидимый знак и использовать стандартный метод делегирования textField:shouldChangeCharactersInRange:replacementString:
как следует
-
Создать невидимый знак
private struct Constants {
static let InvisibleSign = "\u{200B}"
}
-
Установить делегат для textField
textField.delegate = self
-
В событии 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
}
}
}
![введите описание изображения здесь]()
-
Добавить реализацию метода делегата 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
}
}
Ответ 5
Попробуйте это
public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if(string == "") {
print("Backspace pressed");
return true;
}
}
Примечание. Вы можете вернуть " true", если вы хотите разрешить backspace. Иначе вы можете вернуть " false".
Ответ 6
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
}
}
Ответ 7
Пожалуйста, не трогайте свой код. Просто поместите это расширение где-нибудь в своем коде.
Swift 5.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
Swift 4
Я считаю, сравнение с использованием strcmp
не имеет значения. Мы даже не знаем, как strcmp
работает за капюшоном. Во всех остальных ответах при сравнении текущих результатов char и \b
-8
в объектных C и -92
в Swift. Я написал этот ответ, потому что вышеупомянутые решения не сработали для меня. (Версия Xcode 9.3 (9E145)
с использованием Swift 4.1
)
FYI: Каждый персонаж, который вы на самом деле печатаете, представляет собой массив из 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
}
Ответ 9
Я реализовал эту функцию:
![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 за ответ
Ответ 10
Swift 4: Если пользователь нажимает кнопку backspace, строка пуста, поэтому этот подход заставляет textField принимать символы только из заданного набора символов (в данном случае символов utf8) и backspaces (string. isEmpty).
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
}
}
Ответ 11
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
}
}
Ответ 12
Swift Code 3 и > then
func keyboardInputShouldDelete(_ textField: UITextField) -> Bool {
return true
}