Wykryj backspace w pustym UITextField

126

Czy istnieje sposób, aby wykryć naciśnięcie klawisza Backspace/ Deletena klawiaturze iPhone'a na UITextFieldpustej klawiaturze ? Chcę wiedzieć, kiedyBackspace jest wciśnięty, tylko jeśli UITextFieldjest pusty.


Bazując na sugestii @Alex Reynolds w komentarzu, podczas tworzenia mojego pola tekstowego dodałem następujący kod:

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

To powiadomienie jest odbierane ( handleTextFieldChangedwywoływana jest funkcja), ale nadal nie po naciśnięciu Backspaceklawisza w pustym polu. Jakieś pomysły?


Wydaje się, że jest pewne zamieszanie wokół tego pytania. Chcę otrzymać powiadomienie o Backspacenaciśnięciu klawisza. Otóż ​​to. Ale rozwiązanie musi również działać, gdy UITextFieldjest już puste.

marcc
źródło
Myślę, że możesz mieć na myśli „tylko wtedy, gdy UITextField jest puste”, a nie „tylko wtedy, gdy klawiatura jest pusta”…?
Steve Harrison
@Steve Harrison: dzięki. Zaktualizowałem to.
marcc
Próbuję zrobić coś podobnego, jakie rozwiązanie dostałeś wtedy? To, co robię, to pole tekstowe w widoku przewijania, kiedy wpisuję tekst, pojawiają się sugestie, a kiedy je klikam, obiekt etykiety jest umieszczany po lewej stronie pola tekstowego. Z góry dziękuję: D
Dough
Rozwiązanie 2011/11 dla pustego UITextField przy użyciu sztuczki uruchomieniowej
Jano
4
Śmiesznie tęsknię za czymś tak trywialnym. To nie powinno być trudne.
Adam Waite

Odpowiedzi:

36

To może być długa szansa, ale może zadziałać. Spróbuj ustawić tekst w polu tekstowym na znak spacji o zerowej szerokości \u200B. Naciśnięcie klawisza Backspace w polu tekstowym, które wydaje się puste, w rzeczywistości spowoduje usunięcie spacji. Następnie możesz po prostu ponownie włożyć spację.

Może nie działać, jeśli użytkownikowi uda się przesunąć karetkę na lewo od pomieszczenia.

Andrzej
źródło
3
@Andrew, zdecydowałem się na takie podejście. Wymagało to trochę kodu, ale z pewnością jest skuteczne. Dzięki za pomoc, zamiast próbować powiedzieć mi, że robię coś źle.
marcc
2
Ta technika może działać na iPhonie> 3.1.3, ale jest hackerska i może się zepsuć w przyszłych wersjach itp. Myślę, że znalazłem czystsze, bardziej stabilne rozwiązanie, jak wykryć naciśnięcie klawisza usuwania klawiatury na iPhonie / iOS .
ma11hew28
6
Mogę potwierdzić, że usunięcie nie zostanie wykryte, jeśli użytkownikowi uda się przesunąć kursor na lewo od miejsca. Jeśli można dowiedzieć się, jak to naprawić, to należy również podklasy UITextFieldi wdrożenie canPerformAction:withSender:do return NOza select:i selectAll:działań, gdy tekst jest równy ciąg @"\u200B".
ma11hew28
2
Problem polega na tym, że to nie działa w przypadku bezpiecznych pól testowych. Jakieś pomysły, jak sobie z tym poradzić?
Kyle Clegg
7
Przepraszam, ale ten pomysł jest zły. To niewiarygodne i nie powinno być akceptowaną odpowiedzią przy 30 lub więcej głosów za. Zamiast tego podklasowałbym UITextField, tak jak wspominali niektórzy inni komentatorzy.
Brian Sachetta
155

Swift 4:


Podklasa UITextField:

// MyTextField.swift
import UIKit

protocol MyTextFieldDelegate: AnyObject {
    func textFieldDidDelete()
}

class MyTextField: UITextField {

    weak var myDelegate: MyTextFieldDelegate?

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

}

Realizacja:

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

}

Cel C:


Podklasa 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

Teraz po prostu dodaj MyTextFieldDelegate do swojego UIViewControlleri ustaw UITextFields myDelegate na 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");
}
Jakub
źródło
9
To najlepsze rozwiązanie. Zaakceptowaną odpowiedzią jest włamanie. Cel C opiera się na podziale na podklasy, a to rozwiązanie wykorzystuje go odpowiednio do rozwiązania problemu.
TJ
Co stanie się z moimi istniejącymi metodami delegata w ViewController klasie, jeśli UITextFieldUIViewController
ustawię delegata mojego pola tekstowego
4
To najwyraźniej nie działa teraz w ios8, z powodu czegoś, co wygląda na błąd Apple: devforums.apple.com/message/1045312#1045312
chug2k
1
Użyłem rozwiązania obejścia błędu ios8, jak w mojej odpowiedzi i zadziałało. Może się przydać tym, którzy szukają rozwiązania.
furkan3ayraktar
1
deleteBackward()nie zostanie wywołana, jeśli was return falsewtextField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
igrrik
41

Aktualizacja: Zobacz odpowiedź JacobCaraballo, aby zapoznać się z przykładem, który zastępuje -[UITextField deleteBackward].

Wyewidencjonuj UITextInput, w szczególności UIKeyInputma deleteBackwardmetodę delegata, która jest zawsze wywoływana po naciśnięciu klawisza Delete. Jeśli robisz coś prostego, możesz rozważyć po prostu podklasę UILabeli dostosowanie jej do UIKeyInputprotokołu, jak to zrobiono w SimpleTextInput i tym przykładzie UIKeyInput dla iPhone'a . Uwaga: UITextInputi jego krewni (w tym UIKeyInput) są dostępni tylko w iOS 3.2 i nowszych.

ma11hew28
źródło
2
To jest właściwa odpowiedź. To nie jest hacky i bardzo proste dzięki szybkiej podklasie UITextField.
Sam,
Właśnie zauważyłem odpowiedź Jacoba poniżej. Daje to szczegółowy przykład.
Sam,
Warto zauważyć, że ta odpowiedź nie działa w iOS 5. Jeśli pole tekstowe jest puste, naciśnięcie klawisza Backspace nie wywoła tej metody.
jfeldman
31

Kod jak następujący:

@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

W końcu zapomnij zmienić właściwość klasy niestandardowej pola tekstowego na „MyTextField”

Jeffrey Loo
źródło
5
To powinna być akceptowana odpowiedź. Czysto, a właściwie odpowiada na pytanie.
Ryan Romanchuk
1
Odpowiada na pytanie ... O ile celujesz w system iOS 6.0+. Niestety, w systemie iOS 5 funkcja deleteBackward nigdy nie została wywołana w Twojej podklasie.
BJ Homer
2
BJ Homer, 93% urządzeń korzysta z systemu iOS 6, więc brak ukierunkowania na iOS 5 generalnie nie jest tak wielkim problemem.
Jonathan.
2
Cieszę się, że przewijałem wystarczająco dużo, aby to znaleźć. W 100% właściwy sposób, aby to zrobić dzisiaj w IOS 7.
MusiGenesis
Widziałem wiele innych odpowiedzi na to pytanie, które są tylko obejściami i prawie żadna z nich nie dotyczy sytuacji, w której klawisz Backspace jest wciśnięty w pustym polu. Jest to jednak doskonałe i naprawdę czysty sposób na zrobienie tego.
Christopher Hannah,
19

Szybka realizacja:

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
źródło
Dzięki, czy mogę wiedzieć, że ta metoda jest zalecana przez Apple lub jest to hack. wydaje się nieudokumentowane dla textfield.
kalpesh jetani
Pracował dla mnie z textView. dzięki za udostępnienie;)
Edouard Barbier
U mnie działało, gdy pole tekstowe jest puste i kliknięto spację.
Ramakrishna
17

Znalazłem inny sposób łatwiejszy niż subclassrozwiązanie. Nawet trochę dziwne, ale działa dobrze.

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

To trochę dziwne, ponieważ wynik porównania to -8. Może w pewnym momencie się mylę C Programming. Ale to dobra robota;)

Jerapong Nampetch
źródło
1
Styl grzbietowy nie jest ustawiony jako „\ b”. Ale jeśli ostrożnie debugujesz, zobaczysz „\ 0”. Otrzymuję więc wynik 0, czyli dwie wartości są równe w metodzie strcmp. const char * stoke = [tekst cStringUsingEncoding: NSASCIIStringEncoding]; const char * backstroke = "\ 0"; // to jest równe \ b -> "\ x08"; strcmp (styl grzbietowy, skok);
Yoon Lee,
Ponadto, zgodnie z definicją strcmp (s1, s2), zwraca 0, jeśli s1 == s2,> 0 s1 jest leksykograficznie większe niż s2 i odwrotnie.
Yoon Lee,
Nie rozumiem, jak to może działać? @YoonLee: czy nie mówisz też o strcmpzwrotach -1, 0, or 1? To było moje zrozumienie.
chug2k
1
w widoku tekstowym zawsze wykrywasz backspace, nawet jeśli nie ma tekstu, pole UITextField jest inne
LolaRun
2
To jest UITextViewDelegatemetoda, nie UITextFieldDelegate.
pkamb
11

Spróbuj delegate

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

Następnie sprawdź, czy to range.length == 1wydaje się mieć miejsce w przypadku backspacetrafienia.

Niklas Alvaeus
źródło
8
Jednak wywoływana tylko wtedy, gdy pole nie jest puste. Zwróć uwagę na oryginalne pytanie. :)
Eric Goldberg
Użyj do tego UITextView.
Oleg
11

użyj poniższego kodu, który pomoże ci wykryć klawisz usuwania klawiatury, nawet jeśli pole tekstowe jest puste.

Cel C :

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

Szybki:

func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return true }
Pritesh
źródło
Tx - właśnie to, czego potrzebowałem. Ale gdzie jest to udokumentowane?
Andy Weinstein,
9

Odpowiedź Niklasa Alvaeusa pomogła mi w podobnym problemie

Ograniczałem wejście do określonego zestawu znaków, ale ignorowałem spacje. Więc musiałem to sprawdzić range.length == 1przed przycięciem NSString. Jeśli to prawda, po prostu zwracam ciąg i nie przycinam go. Zobacz poniżej

 - (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
źródło
Metoda oczekuje wartości logicznej, a nie ciągu jako wartości zwracanej
Pascalius
4

Dla tych, którzy mają problemy z odpowiedzią Jacoba, zaimplementowałem moją podklasę textfield w następujący sposób i działa świetnie!

#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
źródło
czy umiesz napisać kod dla swift. Wystąpił błąd „zbędne potwierdzenie protokołu uikeyinput”
Raj Aggrawal
4

Tak, użyj poniższej metody, aby wykryć klawisz Backspace, gdy pole textField jest puste.

Musisz dodać UITextFieldDelegate

yourTextField.delegate = self (MUSI WYMAGANE)

Szybki:

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

Cel C:

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { 
    return YES; 
}
Himanshu padia
źródło
5
To nawet mnie nie wymaga. Wszystkie inne metody delegatów są wywoływane w momencie wystąpienia zdarzenia.
Hemang
Dziękuję kolego .. Udało ci się. :)
MS.
@ McDonal_11 Myślę, że zapomniałeś ustawić textfield.delegate = self of textfield.
Himanshu padia
Mam ustalone. inne metody delegatów UITextField działają dobrze. Ten sam nie działa. Za czym tęsknię?
McDonal_11
3

Najlepszym zastosowaniem, jakie znalazłem do wykrywania cofania, jest wykrywanie, kiedy użytkownik nacisnął klawisz Backspace w pustym miejscu UITextField. Na przykład, jeśli masz „bąbelkowanych” odbiorców w aplikacji pocztowej, po naciśnięciu klawisza Backspace w elemencie UITextField, wybierany jest ostatni „bąbelkowany” odbiorca.

Można to zrobić w podobny sposób jak odpowiedź Jacoba Caraballo. Ale w odpowiedzi Jacoba, jeśli po UITextFieldnaciśnięciu klawisza Backspace pozostał jeden znak, do czasu odebrania wiadomości delegata UITextFieldtestament będzie już pusty, więc skutecznie wykrywasz backspacepole tekstowe zawierające co najwyżej jeden znak.

Właściwie, jeśli chcesz wykryć backspacena a UITextFieldz dokładnie zerowymi znakami (pustymi), powinieneś wysłać wiadomość do delegateprzed wywołaniem super deleteBackward. Na przykład:

#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

Interfejs dla takiego pola tekstowego wyglądałby mniej więcej tak:

@protocol MyTextFieldDelegate;

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

@protocol MyTextFieldDelegate <UITextFieldDelegate>
@optional
-(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField;
@end
Sam
źródło
2
Aby to zadziałało w iOS8 (gdzie występuje błąd powodujący, że ta metoda delegata nigdy nie jest wywoływana), zobacz tę odpowiedź: stackoverflow.com/a/25862878/893101 . Więcej szczegółów na temat błędu ios8: devforums.apple.com/message/1009150#1009150
pIkEL
2

W systemie iOS 6 metoda deleteBackward jest wywoływana w UITextField po naciśnięciu klawisza Backspace, w tym gdy pole jest puste. Możesz więc utworzyć podklasę UITextField i zapewnić własną implementację deleteBackward (również wywołując super).

Jednak nadal obsługuję iOS 5, więc potrzebuję kombinacji odpowiedzi Andrew i tego.

tracy
źródło
1

:) tylko dla tytułu „Detect backspace”, gdzie używam UIKeyboardTypeNumberPad.

Dziś wieczorem spotykam się z tym samym pytaniem, a poniżej znajduje się mój kod, aby to sprawdzić:

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

Ponieważ z UIKeyboardTypeNumberPad, użytkownik może wprowadzić tylko liczbę lub cofnięcie, więc gdy długość łańcucha wynosi 0, musi to być klawisz Backspace.

Mam nadzieję, że powyższe pomoże.

Jason Lee
źródło
Tak samo jest z każdym typem klawiatury.
ma11hew28
jak podłączyć tę metodę do mojego pola tekstowego?
user230910
1

Zamiast próbować wstępnie konstruować, co BĘDZIE w polu tekstowym lub dowiedzieć się, jaki znak specjalny został wprowadzony w shouldChangeCharactersInRangemetodzie, sugerowałbym wykonanie następujących czynności:

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

Pozwala to na wywołanie metody bezpośrednio po zakończeniu bieżącej operacji. Fajne w tym jest to, że po zakończeniu zmodyfikowana wartość będzie już znajdować się w UITextField. W tym momencie możesz po prostu sprawdzić jego długość i / lub zweryfikować na podstawie tego, co tam jest.

Aaron
źródło
1

Podklasa UITextField nie działała dla mnie w iOS 8.3, metoda deleteBackward nigdy nie została wywołana.

Oto rozwiązanie, z którego korzystałem, działa na wszystkich wersjach iOS 8 i powinno działać również na innych wersjach 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
}
joel.d
źródło
1

W pliku .h dodaj delegata 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;
}   

ulepszone formatowanie

Anjali Prasad
źródło
1

Zaimplementowałem podobne rozwiązanie z niewielkimi ulepszeniami, które powiedzą mi, że jeśli pole tekstowe ma jakąkolwiek wartość, gdy użytkownik naciska klawisz Backspace. Jest to przydatne w moim przypadku, gdy powinienem skupić się na innym polu tekstowym tylko wtedy, gdy pole tekstowe jest puste po naciśnięciu klawisza 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)
    }
}
Hemang
źródło
1

W najpopularniejszej odpowiedzi brakuje jednej rzeczy - możliwości wykrycia, czy pole tekstowe było puste, czy nie.

Oznacza to, że po zastąpieniu metody deleteBackwards () podklasy TextField nadal nie wiadomo, czy pole tekstowe było już puste. (Zarówno przed, jak i po funkcji deleteBackwards () textField.text!jest pustym ciągiem:"" )

Oto moja poprawa, ze sprawdzeniem pustki przed usunięciem.

1. Utwórz protokół delegata rozszerzający UITextFieldDelegate

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

2. Podklasa 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. Zaimplementuj nowy protokół delegata

extension MyViewController: MyTextFieldDelegate {
    func textField(_ textField: UITextField, didDeleteBackwardAnd wasEmpty: Bool) {
        if wasEmpty {
            // do what you want here...
        }
    }
}
Tim
źródło
1

Kompleksowy program obsługi dla pola tekstowego z jednocyfrowym numerem dla Swift 5.1 :

  • Zakładając, że masz outletową kolekcję textFields (również z podłączonymi delegatami)

1 krok

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 krok

final class ViewController: UIViewController {

    @IBOutlet private var textFields: [MyTextField]!

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

3 krok

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
źródło
0

Oto moje rozwiązanie oparte na pomyśle @andrew:

gdzieś, na przykład w viewDidLoad

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

i wtedy

    @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
źródło
0

Możesz sprawdzić tekst widoku / pola tekstu, aby zobaczyć, czy jest pusty i upewnić się, że tekst zastępczy jest również pusty w metodzie delegata shouldChangeTextIn.

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
źródło
-2

Coś takiego:

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

oczywiście hash dotyczy jednego ciągu znaków.

user1375355
źródło
-2

Korzystanie z metody delegata TextField:

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

Dodaj następujący kod w powyższej metodzie, aby wykryć zdarzenie usunięcia

if(textField == YourTextField)
{
    if ([string length] == 0 && range.length > 0)
    {
        // Your Code after deletion of character
    }
}
kalim sayyad
źródło
-3

Aby zachować prostotę, jest to jedyny warunek, który musisz sprawdzić

     if (range.length==1)
Bhumit Mehta
źródło
-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
źródło
2
Może małe wyjaśnienie, gdzie to umieścić?
Alex Cio
-4

W UITextViewDelegate:

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

dla mnie działa dobrze.

aktualizacja dla chińskiego uproszczonego pinyin i chińskiego pisma odręcznego:

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

na podstawie dokumentu mówi:

„Jeśli użytkownik naciśnie klawisz deleteKey, długość zakresu wynosi 1, a pusty obiekt łańcuchowy zastępuje ten pojedynczy znak”.

żartowniś
źródło
1
To pytanie dotyczy UITextField, nie UITextView.
ma11hew28