Обнаружение обратного пространства в пустом поле UITextField
есть ли способ определить, когда Backspace/удалить клавиша нажата на клавиатуре iPhone на UITextField
пустой? Я хочу знать, когда Backspace нажимается только если UITextField
пусто.
основываясь на предложении @Alex Reynolds в комментарии, я добавил следующий код при создании моего текстового поля:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleTextFieldChanged:)
name:UITextFieldTextDidChangeNotification
object:searchTextField];
данное уведомление получил (handleTextFieldChanged
функция вызывается), но все же не тогда, когда я нажимаю Backspace введите в пустое поле. Есть идеи?
кажется, есть некоторая путаница вокруг этого вопроса. Я хочу получить уведомление, когда Backspace клавиша нажата. Вот и все. Но решение должно также работать, когда UITextField
уже пуст.
23 ответа:
Это может быть длинный выстрел, но это может сработать. Попробуйте установить текст текстового поля на символ пробела нулевой ширины
\u200B
. Когда backspace нажимается на текстовое поле, которое кажется пустым, оно фактически удалит ваше пространство. Затем вы можете просто вставить на место.может не работать, если пользователю удается переместить курсор в левую часть пространства.
Swift 4:
подкласс
UITextField
:// MyTextField.swift import UIKit protocol MyTextFieldDelegate { func textFieldDidDelete() } class MyTextField: UITextField { var myDelegate: MyTextFieldDelegate? override func deleteBackward() { super.deleteBackward() myDelegate?.textFieldDidDelete() } }
реализация:
// ViewController.swift import UIKit class ViewController: UIViewController, MyTextFieldDelegate { override func viewDidLoad() { super.viewDidLoad() // initialize textField let input = MyTextField(frame: CGRect(x: 50, y: 50, width: 150, height: 40)) // set viewController as "myDelegate" input.myDelegate = self // add textField to view view.addSubview(input) // focus the text field input.becomeFirstResponder() } func textFieldDidDelete() { print("delete") } }
Цель-C:
подкласс
UITextField
://Header //MyTextField.h //create delegate protocol @protocol MyTextFieldDelegate <NSObject> @optional - (void)textFieldDidDelete; @end @interface MyTextField : UITextField<UIKeyInput> //create "myDelegate" @property (nonatomic, assign) id<MyTextFieldDelegate> myDelegate; @end //Implementation #import "MyTextField.h" @implementation MyTextField - (void)deleteBackward { [super deleteBackward]; if ([_myDelegate respondsToSelector:@selector(textFieldDidDelete)]){ [_myDelegate textFieldDidDelete]; } } @end
теперь просто добавьте MyTextFieldDelegate на
UIViewController
и установитьUITextFields
myDelegate доself
://View Controller Header #import "MyTextField.h" //add "MyTextFieldDelegate" to you view controller @interface ViewController : UIViewController <MyTextFieldDelegate> @end //View Controller Implementation - (void)viewDidLoad { //initialize your text field MyTextField *input = [[MyTextField alloc] initWithFrame:CGRectMake(0, 0, 70, 30)]; //set your view controller as "myDelegate" input.myDelegate = self; //add your text field to the view [self.view addSubview:input]; } //MyTextField Delegate - (void)textFieldDidDelete { NSLog(@"delete"); }
Обновление: См.JacobCaraballo это!--10--> для примера, который переопределяет
-[UITextField deleteBackward]
.проверить
UITextInput
, в частностиUIKeyInput
естьdeleteBackward
метод это всегда вызывается при нажатии клавиши delete. Если вы делаете что-то простое, то вы можете рассмотреть только подклассыUILabel
и заставить его соответствоватьUIKeyInput
протокол, как это сделано SimpleTextInput а это iPhone UIKeyInput пример. Примечание:UITextInput
и его родственники (в том числеUIKeyInput
) доступны только в iOS 3.2 и выше.
код ниже:
@interface MyTextField : UITextField @end @implementation MyTextField - (void)deleteBackward { [super deleteBackward]; //At here, you can handle backspace key pressed event even the text field is empty } @end
наконец, не забудьте изменить свойство пользовательского класса текстового поля на "MyTextField"
Я создал другой способ проще, чем
subclass
решение. Даже его немного странно, но он работает нормально.- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { const char * _char = [text cStringUsingEncoding:NSUTF8StringEncoding]; int isBackSpace = strcmp(_char, "\b"); if (isBackSpace == -8) { // is backspace } return YES; }
это немного странно для результата сравнения -8. Может быть, я ошибусь в какой-то момент
C Programming
. Но его правильная работа ;)
быстрая реализация:
import UIKit protocol PinTexFieldDelegate : UITextFieldDelegate { func didPressBackspace(textField : PinTextField) } class PinTextField: UITextField { override func deleteBackward() { super.deleteBackward() // If conforming to our extension protocol if let pinDelegate = self.delegate as? PinTexFieldDelegate { pinDelegate.didPressBackspace(self) } } }
попробовать
delegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
затем проверить, если
range.length == 1
который, кажется, имеет место, когдаbackspace
- Это хит.
пожалуйста, используйте ниже код это поможет вам обнаружить клавиатуру удалить ключ, даже если вы текстовое поле пусто.
Цель C :
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }
Swift:
func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
ответ Никласа Альвеуса помог мне с аналогичной проблемой
я ограничивал вход в определенный набор символов, но он игнорировал обратные пространства. Так что я его проверил
range.length == 1
перед обрезкойNSString
. Если это правда, я просто возвращаю строку и не обрезаю ее. Смотрите ниже- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSCharacterSet *nonNumberSet = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet]; if (range.length == 1) { return string; } else { return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0); } }
для тех, у кого есть проблемы с ответ Якоба я реализовал свой подкласс textfield следующим образом, и он отлично работает!
#import <UIKit/UIKit.h> @class HTTextField; @protocol HTBackspaceDelegate <NSObject> @optional - (void)textFieldDidBackspace:(HTTextField*)textField; @end @interface HTTextField : UITextField<UIKeyInput> @property (nonatomic, assign) id<HTBackspaceDelegate> backspaceDelegate; @end #import "HTTextField.h" @implementation HTTextField - (void)deleteBackward { [super deleteBackward]; if ([self.backspaceDelegate respondsToSelector:@selector(textFieldDidBackspace:)]){ [self.backspaceDelegate textFieldDidBackspace:self]; } } - (BOOL)keyboardInputShouldDelete:(UITextField *)textField { BOOL shouldDelete = YES; if ([UITextField instancesRespondToSelector:_cmd]) { BOOL (*keyboardInputShouldDelete)(id, SEL, UITextField *) = (BOOL (*)(id, SEL, UITextField *))[UITextField instanceMethodForSelector:_cmd]; if (keyboardInputShouldDelete) { shouldDelete = keyboardInputShouldDelete(self, _cmd, textField); } } if (![textField.text length] && [[[UIDevice currentDevice] systemVersion] intValue] >= 8) { [self deleteBackward]; } return shouldDelete; } @end
да, используйте ниже метод для обнаружения backspace, когда текстовое поле пусто.
нужно добавить UITextFieldDelegate
yourTextField.делегат = self (ОБЯЗАТЕЛЬНО ТРЕБУЕТСЯ)
Swift:
func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
Цель C:
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }
лучшее использование, которое я нашел для обнаружения backspace, - это обнаружение, когда пользователь нажал backspace в пустом
UITextField
. Например, если у вас есть "пузырчатые" получатели в почтовом приложении, когда вы нажмете backspace вUITextField
, он выбирает последнего "пузырчатого" получателя.это можно сделать аналогично ответу Якоба Карабальо. Но в ответе Якоба, если
UITextField
имеет один символ слева, когда вы нажмете backspace, к моменту получения сообщения делегата,UITextField
уже будет пустым, так что вы эффективно обнаруживаетеbackspace
в текстовом поле, содержащем не более одного символа.на самом деле, если вы хотите обнаружить
backspace
наUITextField
С ровно нулевыми символами (пустыми), то вы должны отправить сообщение вdelegate
перед вызовомsuper deleteBackward
. Например:#import "MyTextField.h" //Text field that detects when backspace is hit with empty text @implementation MyTextField #pragma mark - UIKeyInput protocol -(void)deleteBackward { BOOL isTextFieldEmpty = (self.text.length == 0); if (isTextFieldEmpty) { if ([self.delegate respondsToSelector:@selector(textFieldDidHitBackspaceWithEmptyText:)]) { [self.delegate textFieldDidHitBackspaceWithEmptyText:self]; } } [super deleteBackward]; } @end
интерфейс для такого текстового поля будет выглядеть примерно так:
@protocol MyTextFieldDelegate; @interface MyTextField : UITextField @property(nonatomic, weak) id<MyTextFieldDelegate> delegate; @end @protocol MyTextFieldDelegate <UITextFieldDelegate> @optional -(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField; @end
в iOS 6 метод deleteBackward вызывается в поле UITextField при нажатии кнопки backspace, в том числе при пустом поле. Таким образом, вы можете подкласс UITextField и предоставить свою собственную реализацию deleteBackward (вызывая супер также.)
Я все еще поддерживаю iOS 5, хотя мне понадобится комбинация ответа Эндрю и этого.
:) только для названия "Detect backspace", где я использую
UIKeyboardTypeNumberPad
.Я также встречаю тот же вопрос сегодня вечером, и ниже мой код, чтобы узнать это:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSLog([NSString stringWithFormat:@"%d", [string length]]); }
потому что с
UIKeyboardTypeNumberPad
, пользователь может вводить только номер или backspace, поэтому, когда длина строки равна 0, это должен быть ключ backspace.надеюсь, что выше будет делать некоторую помощь.
вместо того, чтобы пытаться предварительно построить то, что будет в текстовом поле или выяснить, какой специальный символ был введен в
shouldChangeCharactersInRange
способ, я бы предложил сделать следующее:[self performSelector:@selector(manageSearchResultsDisplay) withObject:nil afterDelay:0];
Это позволяет вызвать метод непосредственно после завершения текущей операции. Что здорово в этом, так это то, что к моменту его завершения измененное значение уже будет в
UITextField
. В этот момент Вы можете просто проверить его длину и/или проверить на основе того, что там.
подкласс UITextField не работал для меня на iOS 8.3, deleteBackward никогда не вызывался.
вот решение, которое я использовал, работает на всех версиях iOS 8 и должен работать на других версиях iOS, а также
for textField in textFields { textField.text = " " } func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if string == "" && textField.text == " " { // Do stuff here return false } return true }
In .h Файл Добавить делегат UIKeyInput
- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { if ([textField isEqual:_txtFirstDigit]) { }else if([textField isEqual:_txtSecondDigit]) { [_txtFirstDigit becomeFirstResponder]; }else if([textField isEqual:_txtThirdDigit]) { [_txtSecondDigit becomeFirstResponder]; }else if([textField isEqual:_txtFourthDigit]) { [_txtThirdDigit becomeFirstResponder]; } return YES; }
улучшенное форматирование
я реализовал аналогичное решение с незначительными улучшениями, которые скажут мне, что если текстовое поле имеет какое-либо значение, пока пользователь нажал backspace. Это полезно для моего случая, когда я должен сосредоточиться только на другом текстовом поле, если текстовое поле пустое, когда клавиша нажата.
protocol MyTextFieldDelegate : UITextFieldDelegate { func textFieldDidDelete(textField: MyTextField, hasValue: Bool) } override func deleteBackward() { let currentText = self.text ?? "" super.deleteBackward() let hasValue = currentText.isEmpty ? false : true if let delegate = self.delegate as? MyTextFieldDelegate { delegate.textFieldDidDelete(textField: self, hasValue: hasValue) } }
используя метод делегата текстового поля:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
добавить следующий код в выше метод для обнаружения события удаления
if(textField == YourTextField) { if ([string length] == 0 && range.length > 0) { // Your Code after deletion of character } }
+ (BOOL)detectBackspaceOnly:(NSString *)string { for(int i=0 ; i<string.length ; i++){ unichar caract = [string characterAtIndex:i]; if(caract != ' ' && caract != '\n') return NO; } return YES; }
что-то вроде этого:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (![text hash] && ![textField.text length]) [self backspaceInEmptyTextField]; }
конечно хэш для одной символьной строки.
на
UITextViewDelegate
:- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if(text isEqualToString:@""); { NSLog(@"press backspace."); } }
он работает нормально для меня.
обновление для китайского упрощенного пиньинь и китайского рукописного ввода:
- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if (range.length > 0 && [text isEqualToString:@""]) { NSLog(@"press Backspace."); } return YES; }
база на документе сказано:
"если пользователь нажимает
deleteKey
длина диапазона 1 и пустой строковый объект, который заменяет один символ."