iphone uitextfield

iphone - uitextfielddelegate



Detecta el retroceso en UITextField (23)

Swift 4:

Subclase UITextField :

// MyTextField.swift import UIKit protocol MyTextFieldDelegate { func textFieldDidDelete() } class MyTextField: UITextField { var myDelegate: MyTextFieldDelegate? override func deleteBackward() { super.deleteBackward() myDelegate?.textFieldDidDelete() } }

Implementación:

// 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 objetivo:

Subclase 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

Ahora simplemente agregue MyTextFieldDelegate a su UIViewController y configure su UITextFields myDelegate en 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"); }

¿Hay alguna forma de detectar cuándo se presiona la tecla UITextField / Eliminar en el teclado del iPhone en un UITextField que está vacío? Quiero saber cuándo se presiona Retroceso solo si el UITextField está vacío.

Basado en la sugerencia de @Alex Reynolds en un comentario, agregué el siguiente código al crear mi campo de texto:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleTextFieldChanged:) name:UITextFieldTextDidChangeNotification object:searchTextField];

Se recibe esta notificación (se handleTextFieldChanged función handleTextFieldChanged ), pero aún no cuando handleTextFieldChanged la tecla Retroceso en un campo vacío. ¿Algunas ideas?

Parece haber cierta confusión en torno a esta pregunta. Deseo recibir una notificación cuando se presiona la tecla Retroceso . Eso es. Pero la solución también debe funcionar cuando el UITextField ya está vacío.


:) solo por el título "Detectar retroceso", donde uso UIKeyboardTypeNumberPad .

También encuentro la misma pregunta esta noche, y el siguiente es mi código para descubrirlo:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSLog([NSString stringWithFormat:@"%d", [string length]]); }

Porque con UIKeyboardTypeNumberPad , el usuario solo puede ingresar Número o retroceso, por lo que cuando la longitud de la cadena es 0, debe ser la tecla de retroceso.

Espero que lo anterior te ayude.


Actualización: Vea la respuesta de JacobCaraballo para un ejemplo que anula -[UITextField deleteBackward] .

Verifique UITextInput , específicamente UIKeyInput tiene un método delegate deleteBackward que siempre se llama cuando se presiona la tecla delete. Si está haciendo algo simple, entonces puede considerar simplemente subclasificar UILabel y hacerlo conforme al protocolo UIKeyInput , como lo hacen SimpleTextInput y este ejemplo de UIKeyInput de iPhone . Nota: UITextInput y sus parientes (incluida UIKeyInput ) solo están disponibles en iOS 3.2 y versiones posteriores.


Algo como esto:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (![text hash] && ![textField.text length]) [self backspaceInEmptyTextField]; }

por supuesto, el hash es para una cadena de caracteres.


Código como el siguiente:

@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

Por último, olvide cambiar la propiedad de clase personalizada del campo de texto a "MyTextField"


El mejor uso que he encontrado para detectar el retroceso es detectar cuando el usuario ha retrocedido en un UITextField vacío. Por ejemplo, si tiene destinatarios ''borboteados'' en la aplicación de correo, cuando UITextField Retroceso en el UITextField , selecciona el último destinatario UITextField .

Esto se puede hacer de forma similar a la respuesta de Jacob Caraballo. Pero en la respuesta de Jacob, si el UITextField tiene un carácter restante cuando UITextField el retroceso, cuando se recibe el mensaje de delegado, el UITextField ya estará vacío, por lo que está efectivamente detectando el backspace en un campo de texto con un máximo de un carácter.

En realidad, si desea detectar el backspace en un UITextField con exactamente cero caracteres (vacíos), entonces debe enviar el mensaje al delegate antes de la llamada a super deleteBackward . Por ejemplo:

#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

La interfaz para dicho campo de texto se vería así:

@protocol MyTextFieldDelegate; @interface MyTextField : UITextField @property(nonatomic, weak) id<MyTextFieldDelegate> delegate; @end @protocol MyTextFieldDelegate <UITextFieldDelegate> @optional -(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField; @end


En UITextViewDelegate :

- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if(text isEqualToString:@""); { NSLog(@"press backspace."); } }

funciona bien para mi

actualización para chino simplificado pinyin y entrada de escritura china:

- (BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { if (range.length > 0 && [text isEqualToString:@""]) { NSLog(@"press Backspace."); } return YES; }

la base en el documento dice:

"Si el usuario presiona deleteKey , la longitud del rango es 1 y un objeto de cadena vacío reemplaza ese único carácter".


En el archivo .h, agregue el delegado 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; }

formato mejorado


En iOS 6, se llama al método deleteBackward en el UITextField cuando se presiona el retroceso, incluso cuando el campo está vacío. De modo que puede subclasificar UITextField y proporcionar su propia implementación de deleteBackward (invocando super''s también).

Todavía apoyo iOS 5, así que necesitaré una combinación de la respuesta de Andrew y esto.


En lugar de intentar preconfigurar lo que SERÁ en el campo de texto o descubrir qué carácter especial se ha ingresado en el método shouldChangeCharactersInRange , sugeriría hacer lo siguiente:

[self performSelector:@selector(manageSearchResultsDisplay) withObject:nil afterDelay:0];

Esto le permite llamar a un método directamente después de que se complete la operación actual. Lo bueno de esto es que, para cuando se complete, el valor modificado ya estará en UITextField . En ese punto, puede verificar su longitud y / o validar en función de lo que hay allí.


Esto puede ser una posibilidad remota, pero podría funcionar. Intente configurar el texto del campo de texto en un carácter de espacio de ancho cero. Cuando se presiona retroceso en un campo de texto que aparece vacío, en realidad eliminará su espacio. Entonces puedes reinsertar el espacio.

Puede no funcionar si el usuario logra mover el cursor a la izquierda del espacio.


He fundado otra manera más fácil que la solución de subclass . Incluso es un poco extraño pero funciona bien.

- (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; }

Es un poco extraño que el resultado de la comparación sea -8. Tal vez me equivoque en algún punto de la C Programming Pero es el trabajo correcto;)


He implementado la solución similar con mejoras menores que me dirá que si el campo de texto tiene algún valor mientras el usuario ha tocado el espacio de retroceso. Esto es útil para mi caso cuando solo debería centrarme en otro campo de texto si el campo de texto está vacío cuando se presiona la tecla retroceso.

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


Implementación rápida:

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


La respuesta de Niklas Alvaeus me ayudó con un problema similar

Estaba limitando la entrada a un juego de caracteres específico, pero estaba ignorando los espacios vacíos. Así que lo range.length == 1 verificar range.length == 1 antes de recortar el NSString . Si es cierto, simplemente devuelvo la cadena y no la recorto. Vea abajo

- (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); } }


Para los que tienen problemas con la respuesta de Jacob, implementé mi subclase de campo de texto de la siguiente manera y funciona muy bien.

#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


Para mantenerlo simple aquí, es la única condición que debe verificar

if (range.length==1)


Prueba el delegate

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

Luego, compruebe si range.length == 1 que parece ser el caso cuando se golpea el backspace .


Sí, use el método a continuación para detectar el retroceso, cuando textField está vacío.

Necesita agregar UITextFieldDelegate

yourTextField.delegate = self (DEBE REQUERIRSE)

Rápido:

func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }

C objetivo:

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }


Subclases UITextField no funcionó para mí en iOS 8.3, nunca se invocó deleteBackward.

Aquí está la solución que utilicé, funciona en todas las versiones de iOS 8 y debería funcionar también en otras versiones de 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 }


Usando el método Delegado TextField:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

Agregue el siguiente código en el método anterior para detectar el evento de eliminación

if(textField == YourTextField) { if ([string length] == 0 && range.length > 0) { // Your Code after deletion of character } }


utilice el siguiente código que le ayudará a detectar la tecla de eliminación de teclado, incluso si el campo de texto está vacío.

C objetivo :

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }

Swift:

func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }


+ (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; }