Detect Backspace in UITextField

stimmen
96

Gibt es eine Möglichkeit zu erkennen , wenn der Backspace/ DeleteSchlüssel in der iPhone - Tastatur auf einem gedrückt wird , UITextFielddie leer ist? Ich möchte wissen , wenn Backspacegedrückt wird nur , wenn die UITextFieldleer ist.


Basierend auf dem Vorschlag von @ Alex Reynolds in einem Kommentar, habe ich den folgenden Code hinzugefügt, während mein Textfeld zu erstellen:

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

Diese Mitteilung wird empfangen ( handleTextFieldChangedFunktion genannt wird ), aber immer noch nicht , wenn ich drücken Sie die BackspaceTaste in einem leeren Feld. Irgendwelche Ideen?


Es scheint sich um diese Frage einige Verwirrung. Ich möchte eine Benachrichtigung erhalten , wenn die BackspaceTaste gedrückt wird. Das ist es. Aber die Lösung muss auch funktionieren , wenn die UITextFieldbereits leer ist.

Veröffentlicht am 30/12/2009 um 02:21
quelle vom benutzer
In anderen Sprachen...                            


26 antworten

stimmen
33

Dies kann eine lange gedreht, aber es könnte funktionieren. Versuchen Sie, das Textfeld Text auf eine Breite von Null Leerzeichen einstellen \u200B. Wenn Backspace auf einem Textfeld gedrückt wird , die leer erscheint, wird es tatsächlich Ihren Raum löschen. Dann können Sie einfach den Platz wieder ein .

Kann nicht funktionieren, wenn der Benutzer den Cursor an der linken Seite des Raumes zu bewegen verwaltet.

Beantwortet am 31/12/2009 um 00:10
quelle vom benutzer

stimmen
10

versuchen Sie, die delegate

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

Prüfen Sie dann , ob die range.length == 1was der Fall zu sein scheint , wenn backspacegetroffen wird.

Beantwortet am 16/04/2010 um 17:01
quelle vom benutzer

stimmen
8

Niklas Alvaeus Antwort half mir mit einem ähnlichen Problem

Ich wurde zu einem bestimmten Zeichensatz zu begrenzen Eintrag, aber es war zu ignorieren Marke zurück. Also musste ich es überprüfen , range.length == 1bevor das Trimmen NSString. Wenn es wahr ist, kehre ich nur die Zeichenfolge und nicht trimmen. Siehe unten

 - (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);
    }   
 }
Beantwortet am 30/04/2010 um 14:08
quelle vom benutzer

stimmen
36

Aktualisieren: Siehe JacobCaraballo Antwort für ein Beispiel , das überschreibt -[UITextField deleteBackward].

Check out UITextInput, speziell UIKeyInputhat eine deleteBackwarddelegierte Methode , die immer aufgerufen wird , wenn die Löschtaste gedrückt wird. Wenn Sie einfach etwas zu tun sind, dann könnten Sie nur Subklassen UILabelund machen es dem entsprechen UIKeyInputProtokoll, wie es getan SimpleTextInput und dieses iPhone UIKeyInput Beispiel . Hinweis: UITextInputund seine Verwandten (einschließlich UIKeyInput) sind nur in iOS 3.2 und höher verfügbar.

Beantwortet am 09/07/2011 um 23:14
quelle vom benutzer

stimmen
1

Nur für den Titel „Detect Backspace“ :), wo ich verwende UIKeyboardTypeNumberPad.

Ich treffe auch die gleiche Frage heute Abend, und folgende ist mein Code, es herauszufinden:

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

Denn mit UIKeyboardTypeNumberPad, kann der Benutzer nur Eingabenummer oder Backspace, so dass , wenn die Länge der Zeichenkette 0 ist, muss es Rücktaste sein.

Hoffe, dass die oben wird etwas Hilfe tun.

Beantwortet am 26/12/2011 um 13:55
quelle vom benutzer

stimmen
17

Ich habe andere Art und Weise gegründet einfacher als subclassLösung. Auch seine wenig seltsam , aber es funktioniert ok.

- (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 ist ein wenig seltsam für Ergebnis vergleichen ist -8. Vielleicht werde ich falsch in einem gewissen Punkt der C Programming. Aber seine richtige Arbeit;)

Beantwortet am 20/02/2012 um 04:33
quelle vom benutzer

stimmen
-2

Etwas wie das:

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

natürlich der Hash ist eine Zeichenfolge.

Beantwortet am 02/08/2012 um 04:25
quelle vom benutzer

stimmen
2

In iOS 6 wird die deleteBackward Methode auf dem UITextField aufgerufen, wenn die Rücktaste gedrückt wird, auch wenn das Feld leer ist. So können Sie UITextField Unterklasse und geben Sie Ihre eigenen deleteBackward Implementierung (Super ist auch aufgerufen wird.)

Ich unterstütze immer noch iOS 5 aber so werde ich eine Kombination von Andrew Antwort und diese brauchen.

Beantwortet am 22/10/2012 um 19:28
quelle vom benutzer

stimmen
1

Anstatt zu versuchen , preconstruct was im Textfeld wird oder herausfinden , was Sonderzeichen hat in der eingegeben shouldChangeCharactersInRangeMethode, würde ich vorschlagen , wie folgt vorgehen:

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

Auf diese Weise können Sie eine Methode direkt aufrufen , nachdem der aktuelle Vorgang abgeschlossen ist . Was ist das cool ist , dass durch die Zeit, die abgeschlossen ist , wird der geänderte Wert bereits in der sein UITextField. An diesem Punkt können Sie einfach überprüfen Sie die Länge und / oder Validierung auf das, was da ist.

Beantwortet am 04/12/2012 um 21:19
quelle vom benutzer

stimmen
-4

in UITextViewDelegate:

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

es funktioniert für mich ok.

Update für vereinfachtes Chinesisch Pinyin und chinesische Handschrift-Eingabe:

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

Basis auf dem Dokument heißt es:

„Wenn der Benutzer das presst deleteKey, ist die Länge des Bereichs 1 und ein leeres String - Objekt ersetzt , daß einzelne Zeichen.“

Beantwortet am 30/03/2013 um 07:59
quelle vom benutzer

stimmen
96

Swift 4:


Unterklasse UITextField:

// MyTextField.swift
import UIKit

protocol MyTextFieldDelegate {
    func textFieldDidDelete()
}

class MyTextField: UITextField {

    var myDelegate: MyTextFieldDelegate?

    override func deleteBackward() {
        super.deleteBackward()
        myDelegate?.textFieldDidDelete()
    }

}

Implementierung:

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

}

Ziel c:


Unterklasse 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

Nun fügen Sie einfach MyTextFieldDelegate zu Ihrem UIViewControllerund stellen Sie Ihre UITextFields MyDelegate zu 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");
}
Beantwortet am 04/04/2013 um 02:52
quelle vom benutzer

stimmen
29

Code wie folgt vor:

@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

Endlich, vergessen Sie die Custom Class-Eigenschaft des Textfeldes auf „myTextField“ zu ändern

Beantwortet am 24/04/2013 um 03:41
quelle vom benutzer

stimmen
-2

Einfach hier, um es zu halten ist die einzige Bedingung, u müssen prüfen

     if (range.length==1)
Beantwortet am 05/06/2013 um 06:44
quelle vom benutzer

stimmen
3

Die beste Verwendung , die ich zum Nachweis Backspace gefunden habe , ist festzustellen , wenn der Benutzer Backspace in einem leeren gedrückt hat UITextField. Zum Beispiel, wenn Sie ‚sprudelte‘ Empfänger in dem Mail - App haben, wenn Sie Backspace in dem Hit UITextField, wählt er den letzten ‚sprudelte‘ Empfänger.

Dies kann in ähnlicher Weise wie Jacob Caraballo Antwort erfolgen. Aber in Jakobs Antwort, wenn das UITextFieldein Zeichen mehr hat , wenn Sie Backspace getroffen, durch die Zeit , die Delegierten Nachricht empfangen wird, die UITextFieldbereits leer sein, so dass Sie effektiv Erkennung backspaceauf einem Textfeld mit höchstens einem Zeichen.

Eigentlich, wenn Sie ermitteln möchten backspaceauf einem UITextFieldmit genau null Zeichen (leer), dann sollten Sie die Nachricht an die schicken delegatevor dem Aufruf super deleteBackward. Beispielsweise:

#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

Die Schnittstelle für einen solchen Textfeld würde wie folgt aussehen:

@protocol MyTextFieldDelegate;

@interface MyTextField : UITextField
@property(nonatomic, weak) id<MyTextFieldDelegate> delegate;
@end

@protocol MyTextFieldDelegate <UITextFieldDelegate>
@optional
-(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField;
@end
Beantwortet am 11/07/2013 um 18:39
quelle vom benutzer

stimmen
-2
+ (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;
}
Beantwortet am 21/03/2014 um 11:33
quelle vom benutzer

stimmen
-1

Mit Hilfe der TextField- Delegate-Methode:

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

Fügen Sie den folgenden Code in obigen Verfahren löschen Ereignis zu erfassen,

if(textField == YourTextField)
{
    if ([string length] == 0 && range.length > 0)
    {
        // Your Code after deletion of character
    }
}
Beantwortet am 02/07/2014 um 10:08
quelle vom benutzer

stimmen
4

Für diejenigen , die Probleme über die hat Jakobs Antwort implementiert ich meine Textfeld Unterklasse wie folgt und es funktioniert super!

#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
Beantwortet am 20/10/2014 um 21:46
quelle vom benutzer

stimmen
1

Subclassing UITextField nicht für mich 8.3 auf iOS arbeiten, wurde deleteBackward nie genannt.

Hier ist die Lösung, die ich verwenden, funktioniert auf allen iOS 8 Versionen und soll auch auf anderen iOS-Versionen

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
}
Beantwortet am 20/05/2015 um 20:26
quelle vom benutzer

stimmen
15

Swift Umsetzung:

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)
        }
    }
}
Beantwortet am 06/01/2017 um 02:46
quelle vom benutzer

stimmen
7

bitte unten Code verwenden, es wird Ihnen helfen, Tastaturtaste löschen zu erkennen, auch wenn Sie Textfeld leer ist.

Ziel c :

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

Swift:

func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
Beantwortet am 05/06/2017 um 11:36
quelle vom benutzer

stimmen
4

Yup, verwenden unter Methode Backspace zu erfassen, wenn Textfield leer ist.

Hinzufügen müssen UITextFieldDelegate

yourTextField.delegate = selbst (MUST ERFORDERLICH)

Schnell:

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

Ziel c:

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { 
    return YES; 
}
Beantwortet am 26/07/2017 um 12:54
quelle vom benutzer

stimmen
1

In .h-Datei hinzufügen UIKeyInput Delegat

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

verbesserte Formatierung

Beantwortet am 16/03/2018 um 07:01
quelle vom benutzer

stimmen
0

Ich habe die ähnliche Lösung mit geringfügigen Verbesserungen implementiert, die mir sagen, dass, wenn das Textfeld einen beliebigen Wert hat, während der Benutzer die Rück angezapft hat. Dies ist nützlich für meinen Fall, wenn ich nur auf einem anderen Textfeld konzentrieren sollte, wenn das Textfeld leer ist, wenn Backspace gedrückt.

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)
    }
}
Beantwortet am 21/05/2018 um 08:07
quelle vom benutzer

stimmen
1

Die Pappel Antwort fehlt eine Sache - die Fähigkeit , zu erkennen , ob das Textfeld leer war oder nicht.

Das heißt, wenn Sie die deleteBackwards außer Kraft setzen () -Methode eines TextField- Unterklasse, Sie wissen noch nicht , ob das Textfeld bereits leer war. (Sowohl vor als auch nach deleteBackwards (), textField.text!ist eine leere Zeichenfolge: "")

Hier ist meine Verbesserung, mit einem Scheck über Leere vor dem Löschen.

1. Erstellen Sie einen Delegaten-Protokoll, das UITextFieldDelegate erstreckt

protocol MyTextFieldDelegate: UITextFieldDelegate {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool)
}

2. Subclass UITextField

class MyTextField: UITextField {
    override func deleteBackward() {
        // see if text was empty
        let wasEmpty = text == nil || text! == ""

        // then perform normal behavior
        super.deleteBackward()

        // now, notify delegate (if existent)
        (delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
    }
}

3. Implementieren Sie Ihren neuen Delegierten Protokoll

extension MyViewController: MyTextFieldDelegate {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
        if wasEmpty {
            // do what you want here...
        }
    }
}
Beantwortet am 15/01/2019 um 21:50
quelle vom benutzer

stimmen
0

Umfassende Handler für Textfeld mit einstelliger Zahl für Swift 5.1 :

  • Unter der Annahme, dass Sie (wie auch mit angeschlossenen Teilnehmern) outlet Sammlung von Textfeldern haben

1 Schritt

protocol MyTextFieldDelegate: class {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) 
}

final class MyTextField: UITextField {

    weak var myDelegate: MyTextFieldDelegate?

    override func deleteBackward() {
        let wasEmpty = text == nil || text == ""

        // then perform normal behavior
        super.deleteBackward()

        // now, notify delegate (if existent)
        (delegate as? MyTextFieldDelegate)?.textField(self, didDeleteBackwardAnd: wasEmpty)
    }
}

2 Schritt

final class ViewController: UIViewController {

    @IBOutlet private var textFields: [MyTextField]!

    override func viewDidLoad() {
        super.viewDidLoad()
        textFields.forEach {
            $0.delegate = self
            $0.myDelegate = self
        }
    }
}

Schritt 3

extension ViewController: UITextFieldDelegate, MyTextFieldDelegate {
    func textFieldHasChanged(with text: String, _ tag: Int, for textField: UITextField) {
        textField.text = text

        if let someTextField = (textFields.filter { $0.tag == tag }).first {
            someTextField.becomeFirstResponder()
        } else {
            view.endEditing(true)
        }
    }

    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
        // If the user was pressing backward and the value was empty, go to previous textField
        textFieldHasChanged(with: "", textField.tag - 1, for: textField)
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // Restrict to only digits
        let aSet = NSCharacterSet(charactersIn: "0123456789").inverted
        let compSepByCharInSet = string.components(separatedBy: aSet)
        let numberFiltered = compSepByCharInSet.joined(separator: "")

        guard string == numberFiltered, let text = textField.text else { return false }

        if text.count >= 1 && string.isEmpty {
            // If the user is deleting the value
            textFieldHasChanged(with: "", textField.tag - 1, for: textField)
        } else {
            textFieldHasChanged(with: string, textField.tag + 1, for: textField)
        }

        return false
    }
}
Beantwortet am 15/12/2019 um 03:32
quelle vom benutzer

stimmen
0

Hier ist meine Lösung, die auf @ Andrew Idee:

irgendwo, zum Beispiel in viewDidLoad

        textField.delegate = self
        textField.addTarget(self, action: #selector(valueChanged(_:)), for: .editingDidBegin)

und dann

    @objc func valueChanged(_ textField: UITextField) {
        textField.text = "\u{200B}"
    }

    override func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        textField.text = string
        if string == "" {
            //backpaspace pressed 
        }
Beantwortet am 16/12/2019 um 12:20
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more