Erkennen Sie die Rücktaste im leeren UITextField

126

Gibt es eine Möglichkeit zu erkennen, wann die Taste Backspace/ Deleteauf der iPhone-Tastatur eines UITextFieldleeren Geräts gedrückt wird? Ich möchte wissen, wann Backspacenur gedrückt wird, wenn das UITextFieldleer ist.


Basierend auf dem Vorschlag von @Alex Reynolds in einem Kommentar habe ich beim Erstellen meines Textfelds den folgenden Code hinzugefügt:

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

Diese Benachrichtigung wird empfangen ( handleTextFieldChangedFunktion wird aufgerufen), aber immer noch nicht, wenn ich die BackspaceTaste in einem leeren Feld drücke . Irgendwelche Ideen?


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

marcc
quelle
Ich denke, Sie meinen vielleicht "nur wenn das UITextField leer ist" anstatt "nur wenn die Tastatur leer ist" ...?
Steve Harrison
@ Steve Harrison: Danke. Das wurde aktualisiert.
März
Ich versuche etwas Ähnliches zu tun. Welche Lösung haben Sie dann bekommen? Was ich tue, ist ein Textfeld in einer Bildlaufansicht. Wenn ich Text eingebe, werden Vorschläge angezeigt und wenn ich auf eines klicke, wird links neben dem Textfeld ein Beschriftungsobjekt platziert. Vielen Dank im Voraus: D
Teig
2011/11 Lösung für leeres UITextField mit Laufzeit-Tricks: bjhomer.blogspot.com/2011/11/…
Jano
4
Lächerlich sehnen Sie sich nach etwas so Trivialem. Das sollte nicht schwierig sein.
Adam Waite

Antworten:

36

Dies mag ein langer Weg sein, aber es könnte funktionieren. Versuchen Sie, den Text des Textfelds auf ein Leerzeichen mit der Breite Null festzulegen \u200B. Wenn in einem leeren Textfeld die Rücktaste gedrückt wird, wird Ihr Leerzeichen tatsächlich gelöscht. Dann können Sie den Raum einfach wieder einfügen.

Funktioniert möglicherweise nicht, wenn der Benutzer es schafft, das Caret links vom Feld zu verschieben.

Andrew
quelle
3
@ Andrew, das ist der Ansatz, für den ich mich entschieden habe. Es hat ein bisschen Code gekostet, aber es ist auf jeden Fall effektiv. Vielen Dank für die Hilfe, anstatt mir zu sagen, dass ich etwas falsch mache.
März
2
Diese Technik funktioniert möglicherweise auf dem iPhone> 3.1.3, ist jedoch hackig und kann in zukünftigen Versionen usw. nicht funktionieren. Ich glaube, ich habe eine sauberere und stabilere Lösung gefunden , um einen Tastendruck beim Löschen der Tastatur auf dem iPhone / iOS zu erkennen .
ma11hew28
6
Ich kann bestätigen, dass das Löschen nicht erkannt wird, wenn der Benutzer den Cursor links vom Leerzeichen bewegt. Wenn Sie herausfinden , wie das beheben, dann sollten Sie auch eine Unterklasse UITextFieldund implementieren , canPerformAction:withSender:um return NOfür select:und selectAll:Aktionen , wenn der Text in der Zeichenfolge entspricht @"\u200B".
ma11hew28
2
Problem ist, dass dies für sichere Testfelder nicht funktioniert. Irgendwelche Ideen, wie man damit umgeht?
Kyle Clegg
7
Entschuldigung, aber diese Idee ist schlecht. Es ist unglaublich hackig und sollte nicht die akzeptierte Antwort mit 30 oder so positiven Stimmen sein. Ich würde stattdessen UITextField unterordnen, wie einige der anderen Kommentatoren erwähnt haben.
Brian Sachetta
155

Swift 4:


Unterklasse UITextField:

// MyTextField.swift
import UIKit

protocol MyTextFieldDelegate: AnyObject {
    func textFieldDidDelete()
}

class MyTextField: UITextField {

    weak 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

Fügen Sie nun einfach MyTextFieldDelegate zu Ihrem hinzu UIViewControllerund setzen Sie UITextFields myDelegate auf 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");
}
Jacob
quelle
9
Dies ist die beste Lösung. Die akzeptierte Antwort ist ein Hack. Ziel C basiert auf einer Unterklassifizierung, und diese Lösung verwendet es ordnungsgemäß, um das Problem zu lösen.
TJ
Was passiert mit meinen vorhandenen Delegatenmethoden in der ViewController Klasse, wenn ich den Delegaten meines Textfelds auf eine Unterklasse UITextFieldanstelle vonUIViewController
rohan-patel
4
Dies funktioniert derzeit in ios8 anscheinend nicht, da es sich anscheinend um einen Apple- Fehler handelt
chug2k
1
Ich habe eine Problemumgehungslösung für den ios8-Fehler wie in meiner Antwort verwendet und es hat funktioniert. Dies kann für diejenigen nützlich sein, die nach einer Lösung suchen.
Furkan3ayraktar
1
deleteBackward()wird nicht angerufen, wenn Sie return falseintextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
igrrik
41

Update: In der Antwort von JacobCaraballo finden Sie ein Beispiel, das überschrieben wird -[UITextField deleteBackward].

Check out UITextInputhat speziell UIKeyInputeine deleteBackwardDelegate-Methode , die immer aufgerufen wird, wenn die Löschtaste gedrückt wird. Wenn Sie etwas Einfaches tun, sollten Sie in Betracht ziehen, es einfach zu unterordnen UILabelund an das UIKeyInputProtokoll anzupassen , wie dies von SimpleTextInput und diesem iPhone UIKeyInput-Beispiel durchgeführt wird . Hinweis: UITextInputund seine Verwandten (einschließlich UIKeyInput) sind nur in iOS 3.2 und höher verfügbar.

ma11hew28
quelle
2
Das ist die richtige Antwort. Es ist nicht hackig und sehr einfach mit einer schnellen Unterklasse von UITextField.
Sam
Ich habe gerade Jacobs Antwort unten gesehen. Es gibt ein detailliertes Beispiel dafür.
Sam
Es ist erwähnenswert, dass diese Antwort in iOS 5 nicht funktioniert. Wenn das Textfeld leer ist, wird diese Methode durch Drücken der Rücktaste nicht aufgerufen.
Jfeldman
31

Code wie folgt:

@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

Vergessen Sie zum Schluss, die Eigenschaft Benutzerdefinierte Klasse des Textfelds in "MyTextField" zu ändern.

Jeffrey Loo
quelle
5
Dies sollte die akzeptierte Antwort sein. Sauber und beantwortet tatsächlich die Frage.
Ryan Romanchuk
1
Es beantwortet die Frage ... Solange Sie auf iOS 6.0+ abzielen. Unter iOS 5 wurde deleteBackward in Ihrer Unterklasse leider nie aufgerufen.
BJ Homer
2
BJ Homer, 93% der Geräte sind mit iOS 6 ausgestattet, daher ist es im Allgemeinen keine so große Sache, nicht auf iOS 5 abzuzielen.
Jonathan.
2
Ich bin froh, dass ich so weit nach unten gescrollt habe, dass ich das gefunden habe. 100% der richtige Weg, dies heute in IOS 7 zu tun.
MusiGenesis
Ich habe so viele andere Antworten auf diese Frage gesehen, die nur Problemumgehungen sind, und kaum eine davon befasst sich mit der Situation, in der die Rücktaste in einem leeren Feld gedrückt wird. Dies ist jedoch perfekt und ein wirklich sauberer Weg, dies zu tun.
Christopher Hannah
19

Schnelle Implementierung:

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)
        }
    }
}
Ruud Visser
quelle
Danke, darf ich wissen, dass diese Methode von Apple empfohlen wird oder es ist Hack. es scheint für Textfeld undokumentiert zu sein.
Kalpesh Jetani
Arbeitete für mich mit einer Textansicht. danke fürs teilen;)
Edouard Barbier
Hat bei mir funktioniert, wenn das Textfeld leer ist und auf die Rücktaste geklickt wird.
Ramakrishna
17

Ich habe anders gegründet als subclassLösung. Sogar es ist ein bisschen seltsam, aber es funktioniert in Ordnung.

- (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 bisschen seltsam für das Ergebnis des Vergleichs ist -8. Vielleicht irre ich mich irgendwann C Programming. Aber es ist die richtige Arbeit;)

Jerapong Nampetch
quelle
1
Rückenschwimmen ist nicht '\ b' gesetzt. Wenn Sie jedoch sorgfältig debuggen, wird '\ 0' angezeigt. Ich erhalte also das Ergebnis 0, dh zwei Werte sind in der strcmp-Methode gleich. const char * stoke = [Text cStringUsingEncoding: NSASCIIStringEncoding]; const char * backstroke = "\ 0"; // dies ist gleich \ b -> "\ x08"; strcmp (Rücken, Schlag);
Yoon Lee
Nach der Definition von strcmp (s1, s2) wird 0 zurückgegeben, wenn s1 == s2,> 0 s1 lexikographisch größer als s2 ist, und umgekehrt.
Yoon Lee
Ich verstehe nicht, wie das möglicherweise funktionieren könnte? @YoonLee: Sagst du nicht auch strcmpRückkehr -1, 0, or 1? Das war mein Verständnis.
Chug2k
1
In der Textansicht erkennen Sie immer die Rücktaste, auch wenn kein Text vorhanden ist. Das UITextField ist anders
LolaRun
2
Dies ist keine UITextViewDelegateMethode, nicht UITextFieldDelegate.
pkamb
11

Probieren Sie die delegate

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

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

Niklas Alvaeus
quelle
8
Wird nur aufgerufen, wenn das Feld nicht leer ist. Beachten Sie die ursprüngliche Frage. :)
Eric Goldberg
Verwenden Sie dazu UITextView.
Oleg
11

Verwenden Sie den folgenden Code, um die Löschtaste der Tastatur zu erkennen, auch wenn Ihr Textfeld leer ist.

Ziel c :

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

Swift:

func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
Pritesh
quelle
Tx - genau das, was ich brauchte. Aber wo ist es dokumentiert?
Andy Weinstein
9

Die Antwort von Niklas Alvaeus half mir bei einem ähnlichen Problem

Ich habe den Eintrag auf einen bestimmten Zeichensatz beschränkt, aber die Leerzeichen ignoriert. Also habe ich es range.length == 1vor dem Trimmen überprüfen lassen NSString. Wenn es wahr ist, gebe ich den String einfach zurück und schneide ihn nicht ab. 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);
    }   
 }
Ben Call
quelle
Die Methode erwartet einen Booleschen Wert und keinen String als Rückgabewert
Pascalius
4

Für diejenigen, die Probleme mit der Antwort von Jacob haben, habe ich meine Textfeld-Unterklasse wie folgt implementiert und es funktioniert großartig!

#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
furkan3ayraktar
quelle
Kannst du den Code für Swift schreiben? Ich habe einen Fehler "redundante Bestätigung für protoco uikeyinput"
Raj Aggrawal
4

Ja, verwenden Sie die folgende Methode, um die Rücktaste zu erkennen, wenn textField leer ist.

Muss hinzufügen UITextFieldDelegate

yourTextField.delegate = self (MUSS ERFORDERLICH sein)

Schnell:

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

Ziel c:

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { 
    return YES; 
}
Himanshu Padia
quelle
5
Das fordert mich nicht einmal. Alle anderen Delegatenmethoden werden aufgerufen, sobald ein Ereignis eintritt.
Hemang
Danke Kumpel .. Du hast es geschafft. :)
MS.
@ McDonal_11 Ich denke, Sie haben vergessen, textfield.delegate = self of textfield zu setzen.
Himanshu Padia
Ich habe gesetzt. Andere Delegate-Methoden von UITextField funktionieren einwandfrei. Dieser alleine funktioniert nicht. Was ich vermisse ??
McDonal_11
3

Die beste Verwendung, die ich zum Erkennen der Rücktaste gefunden habe, ist das Erkennen, wenn der Benutzer die Rücktaste in einem leeren Bereich gedrückt hat UITextField. Wenn Sie beispielsweise Empfänger in der E-Mail-App "gesprudelt" haben, drücken Sie die Rücktaste in derUITextField den letzten "gesprudelten" Empfänger aus.

Dies kann auf ähnliche Weise wie die Antwort von Jacob Caraballo geschehen. Aber in Jacobs Antwort ist das UITextFieldZeichen UITextFieldbereits leer, wenn beim Senden der Rücktaste noch ein Zeichen übrig ist. Wenn die Delegatennachricht empfangen wird, ist das Zeichen bereits leer, sodass Sie es effektiv erkennenbackspace ein Textfeld mit höchstens einem Zeichen erkennen.

Wenn Sie backspaceauf einem UITextFieldmit genau null Zeichen (leer) erkennen möchten, sollten Sie die Nachricht an die delegatevor dem Anruf an senden 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 ein solches Textfeld würde ungefähr so ​​aussehen:

@protocol MyTextFieldDelegate;

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

@protocol MyTextFieldDelegate <UITextFieldDelegate>
@optional
-(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField;
@end
Sam
quelle
2
Damit dies in iOS8 funktioniert (wo es einen Fehler gibt, der dazu führt, dass diese Delegatenmethode nie aufgerufen wird), lesen Sie bitte diese Antwort: stackoverflow.com/a/25862878/893101 . Weitere Details zum ios8-Fehler: devforums.apple.com/message/1009150#1009150
pIkEL
2

In iOS 6 wird die deleteBackward-Methode im UITextField aufgerufen, wenn die Rücktaste gedrückt wird, auch wenn das Feld leer ist. Sie können also UITextField in eine Unterklasse unterteilen und Ihre eigene deleteBackward-Implementierung bereitstellen (auch Super's aufrufen).

Ich unterstütze immer noch iOS 5, daher brauche ich eine Kombination aus Andrews Antwort und dieser.

Tracy
quelle
1

:) nur für den Titel "Detect Backspace", wo ich benutze UIKeyboardTypeNumberPad.

Ich treffe heute Abend auch die gleiche Frage und folge meinem Code, um es herauszufinden:

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

Da mit UIKeyboardTypeNumberPadkann der Benutzer nur die Nummer oder die Rücktaste eingeben. Wenn die Länge der Zeichenfolge 0 ist, muss es sich um die Rücktaste handeln.

Hoffe, dass das oben genannte etwas helfen wird.

Jason Lee
quelle
Dies ist bei jedem Tastaturtyp gleich.
ma11hew28
Wie verbinde ich diese Methode mit meinem Textfeld?
user230910
1

Anstatt zu versuchen, vorab zu konstruieren, was im Textfeld sein wird, oder herauszufinden, welches Sonderzeichen in die shouldChangeCharactersInRangeMethode eingegeben wurde , würde ich Folgendes vorschlagen:

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

Auf diese Weise können Sie eine Methode direkt nach Abschluss des aktuellen Vorgangs aufrufen. Das Coole daran ist, dass der geänderte Wert zum Zeitpunkt des Abschlusses bereits im UITextField. An diesem Punkt können Sie einfach die Länge überprüfen und / oder anhand der vorhandenen Daten validieren.

Aaron
quelle
1

Die Unterklasse UITextField funktionierte unter iOS 8.3 nicht für mich, deleteBackward wurde nie aufgerufen.

Hier ist die Lösung, die ich verwendet habe, die auf allen iOS 8-Versionen funktioniert und die auch auf anderen iOS-Versionen funktionieren sollte

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
}
joel.d
quelle
1

Fügen Sie in der .h-Datei den UIKeyInput-Delegaten hinzu

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

Anjali Prasad
quelle
1

Ich habe die ähnliche Lösung mit geringfügigen Verbesserungen implementiert, die mir mitteilen, dass das Textfeld einen Wert hat, während der Benutzer auf die Rücktaste getippt hat. Dies ist in meinem Fall nützlich, wenn ich mich nur auf ein anderes Textfeld konzentrieren sollte, wenn das Textfeld leer ist, wenn die Rücktaste gedrückt wird.

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)
    }
}
Hemang
quelle
1

Bei der Antwort mit den meisten Pappeln fehlt eines - die Fähigkeit zu erkennen, ob das Textfeld leer war oder nicht.

Wenn Sie also die deleteBackwards () -Methode einer TextField-Unterklasse überschreiben, wissen Sie immer 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 einer Überprüfung der Leere vor dem Löschen.

1. Erstellen Sie ein Delegatenprotokoll, das UITextFieldDelegate erweitert

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

2. Unterklasse 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 Ihr neues Delegatenprotokoll

extension MyViewController: MyTextFieldDelegate {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
        if wasEmpty {
            // do what you want here...
        }
    }
}
Tim
quelle
1

Umfassender Handler für Textfelder mit einstelliger Nummer für Swift 5.1 :

  • Angenommen, Sie haben eine Outlet-Sammlung von textFields (auch mit verbundenen Delegaten).

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

3 Schritt

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
    }
}
Latenec
quelle
0

Hier meine Lösung basierend 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 
        }
rastislv
quelle
0

Sie können den Text der Textansicht / des Textfelds überprüfen, um festzustellen, ob er leer ist, und sicherstellen, dass der Ersatztext auch in der delegate-Methode shouldChangeTextIn leer ist.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if (textView.text == "" && text == "") {
        print("Backspace on empty text field.")
    }
    return true
}
michael-k101
quelle
-2

Etwas wie das:

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

Natürlich ist der Hash für eine Zeichenkette.

user1375355
quelle
-2

Verwenden der TextField Delegate-Methode:

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

Fügen Sie den folgenden Code in der obigen Methode hinzu, um ein Löschereignis zu erkennen

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

Um es einfach zu halten, ist hier die einzige Bedingung, die Sie überprüfen müssen

     if (range.length==1)
Bhumit Mehta
quelle
-3
+ (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;
}
K-AnGaMa
quelle
2
Vielleicht eine kleine Erklärung, wo man das hinstellt?
Alex Cio
-4

In UITextViewDelegate:

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

es funktioniert ok für mich.

Update für chinesische vereinfachte Pinyin- und chinesische Handschrifteingabe:

- (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 sagt:

"Wenn der Benutzer die Taste drückt deleteKey, beträgt die Länge des Bereichs 1, und ein leeres Zeichenfolgenobjekt ersetzt dieses einzelne Zeichen."

Joker
quelle
1
Diese Frage ist etwa UITextField, nicht UITextView.
ma11hew28