2015-04-08 23 views
14

Szukam rozwiązań dotyczących przechwytywania zdarzenia Backspace, większość odpowiedzi w Stack Overflow jest w Objective-C, ale potrzebuję języka Swift.Wykryj zdarzenie Backspace w UITextField

najpierw muszę ustawić delegata dla UITextField i ustawić ją na siebie

self.textField.delegate = self; 

Wtedy wiem użyć shouldChangeCharactersInRange metodę delegata wykryć, czy został naciśnięty klawisz backspace jest cały kod są w Objective-C. Potrzebuję w Swift tej metody, jak poniżej.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { 
    const char * _char = [string cStringUsingEncoding:NSUTF8StringEncoding]; 
    int isBackSpace = strcmp(_char, "\b"); 

    if (isBackSpace == -8) { 
     // NSLog(@"Backspace was pressed"); 
    } 

    return YES; 
} 
+2

Jak wygląda Twoje podejście do problemu Swift? Proszę. Pokaż nam swój wysiłek i pomóżmy Ci, gdzie jest źle. Stack Overflow nie jest usługą pisania kodu. – nhgrif

+0

Szukam również tego rozwiązania. Jeśli ktokolwiek wie, proszę o odpowiedź. –

Odpowiedz

32

nadzieję, że pomoże: p

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 
    let char = string.cStringUsingEncoding(NSUTF8StringEncoding)! 
    let isBackSpace = strcmp(char, "\\b") 

    if (isBackSpace == -92) { 
     println("Backspace was pressed") 
    } 
    return true 
} 
+0

Ta metoda przekazywania nie jest uruchamiana. Delegat jest ustawiony w metodzie 'viewDidLoad()'. –

+6

to działa świetnie, chyba że textField nie jest pusty – gbk

+2

-1: ten kod działa, ale przez przypadek. [Dokumentacja] (https://developer.apple.com/documentation/uikit/uitextfielddelegate/1619599-textfield) określa, że ​​'ciąg' będzie pustym ciągiem znaków, jeśli użytkownik usunie jeden lub więcej znaków. – ravron

6

Spróbuj

public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 

if(string == "") { 

     print("Backspace pressed"); 
     return true; 
    } 
} 

Uwaga: Można powrócić "prawda" jeśli chcesz zezwolić Backspace. W przeciwnym razie możesz zwrócić "false".

+1

Co się stanie, jeśli bieżący tekst jest pusty? –

+0

Ten delegat nie zostanie nazwany –

+3

'string ==" "zamiast tego lepiej użyj' .isEmpty' – gbk

8

Jeśli potrzebujesz wykrycia backspace nawet w pustym textField (na przykład jeśli potrzebujesz automatycznego przełączenia z powrotem na prev textField na backSpace press), możesz użyć kombinacji proponowanych metod - dodaj niewidoczny znak i użyj standardowej metody delegowania textField:shouldChangeCharactersInRange:replacementString: śledzić

  1. Tworzenie niewidoczny znak

    private struct Constants { 
        static let InvisibleSign = "\u{200B}" 
    } 
    
  2. Set delegat na textField

    textField.delegate = self 
    
  3. Na wydarzenie EditingChanged tekstu wyboru i jeśli potrzebne dodać niewidoczny symbol jak następujące:

    @IBAction func didChangeEditingInTextField(sender: UITextField) { 
        if var text = sender.text { 
         if text.characters.count == 1 && text != Constants.InvisibleSign { 
          text = Constants.InvisibleSign.stringByAppendingString(text) 
          sender.text = text 
         } 
        } 
    } 
    

enter image description here

  1. Dodaj wdrożenie metody delegata textField:shouldChangeCharactersInRange:replacementString:

    extension UIViewController : UITextFieldDelegate { 
        // MARK: - UITextFieldDelegate 
        func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 
    
         let char = string.cStringUsingEncoding(NSUTF8StringEncoding)! 
         let isBackSpace = strcmp(char, "\\b") 
    
         if (isBackSpace == -92) { 
          if var string = textField.text { 
           string = string.stringByReplacingOccurrencesOfString(Constants.InvisibleSign, withString: "") 
           if string.characters.count == 1 { 
            //last visible character, if needed u can skip replacement and detect once even in empty text field 
            //for example u can switch to prev textField 
            //do stuff here        
           } 
          } 
         } 
         return true 
        } 
    } 
    
13

w Swift 3

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 
    let char = string.cString(using: String.Encoding.utf8)! 
    let isBackSpace = strcmp(char, "\\b") 

    if (isBackSpace == -92) { 
     print("Backspace was pressed") 
    } 
    return true 
} 

:)

1

Swift 4: Jeśli użytkownik naciśnie przycisk Backspace, łańcuch jest pusty, więc to siły podejście textField tylko akceptować znaki z określonego zestaw znaków (w tym przypadku utf8 znaków) i backspace (przypadek string.isEmpty).

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { 
    if string.cString(using: String.Encoding.utf8) != nil { 
     return true 
    } else if string.isEmpty { 
     return true 
    } else { 
     return false 
    } 
} 
0

Kod Swift 3 i> wtedy

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

    return true 
} 
0

Wolę subclassing UITextField i nadrzędnym deleteBackward() dlatego, że jest dużo bardziej niezawodny niż hack korzystania shouldChangeCharactersInRange:

class MyTextField: UITextField { 
    override public func deleteBackward() { 
     if text == "" { 
      // do something when backspace is tapped/entered in an empty text field 
     } 
     // do something for every backspace 
     super.deleteBackward() 
    } 
} 

shouldChangeCharactersInRange technikę w połączeniu z niewidzialną postacią umieszczoną w polu tekstowym ma kilka wad:

  • z klawiaturą dołączony, można umieścić kursor przed niewidzialnym charakterem i Backspace nie jest wykrywany już,
  • użytkownik może nawet wybrać tę niewidzialną postać (używając Shift Arrow na klawiaturze lub nawet dotykając na daszek) i będzie mylić o tej dziwnej postaci,
  • pasek autouzupełnianie oferuje dziwnych wyborów tak długo, jak istnieje tylko ta niewidzialna postać,
  • placeholder nie zostanie pokazany już,
  • wyświetlany jest jasne, przycisk nawet kiedy to ty Nie dla clearButtonMode = .whileEditing.

Oczywiście, przesłonięcie deleteBackward() jest nieco niewygodne ze względu na potrzebę podklasy. Ale im lepszy UX, tym warty jest wysiłek!

A jeśli podklasowanie nie jest możliwe, np. podczas korzystania z UISearchBar z wbudowanym UITextField, metoda swizzling powinna być również dobra.