2012-08-01 11 views
6

Mam zaimplementowaną niestandardową klawiaturę powiązaną z polem tekstowym, więc kiedy użytkownik naciśnie przycisk usuwania, usuwam ostatni znak z ciągu i ręcznie aktualizuję bieżący tekst pola tekstowego .Jak usunąć ostatni symbol Unicode z NSString

NSRange range = NSMakeRange(currentTextFieldString.length-1, 1); 
[currentTextFieldString replaceCharactersInRange:range withString:@""]; 

Jak dotąd tak dobrze.

Problem polega na tym, że użytkownik ma możliwość wprowadzenia specjalnych symboli unikodowych, nie są one 1-bajtowe, mogą też być 2-bajtowe, teraz po naciśnięciu przycisku kasowania, muszę usunąć cały symbol , ale jeśli postępuję zgodnie z powyższym podejściem, użytkownik musi dwukrotnie nacisnąć przycisk usuwania.

Tutaj, jeśli mam zrobić:

NSRange range = NSMakeRange(currentTextFieldString.length-2, 2); 
[currentTextFieldString replaceCharactersInRange:range withString:@""]; 

to działa dobrze, ale potem, zwykłe znaki, które są tylko 1 bajt, zostaną usunięte dwa razy w tym samym czasie.

Jak radzić sobie z takimi scenariuszami?

Z góry dziękuję.

EDIT:

To dziwne, że jeśli mogę przełączyć na klawiaturze iPhone, obsługuje oba przypadki odpowiednio. Musi być jakiś sposób, aby to zrobić, jest coś, czego mi brakuje, ale nie jestem w stanie dowiedzieć się, co.

+0

Jak twoja niestandardowa klawiatura dodaje znaki? – Joe

+0

Moja odpowiedź na to pytanie może Ci pomóc http://stackoverflow.com/q/11567049/1487063 – Dustin

+0

@Joe: gdy użytkownik naciśnie przycisk, łapię odpowiedni znak, dołączam go do bieżącego tekstu w polu tekstowym, i przypisz go jako tekst pola tekstowego. –

Odpowiedz

16

Oto problem. NSStrings są kodowane za pomocą UTF-16. Wiele popularnych glifów Unicode przyjmuje tylko jedną wartość unichar (16-bitową wartość bez znaku). Jednak niektóre glify zajmują dwa unichary. Co gorsza, niektóre glify można komponować lub rozkładać, np. Może to być jeden kodowy kod Unicode lub dwa - ostry akcent, a następnie e. To sprawia, że ​​dość trudno jest zrobić to, co chcesz, a mianowicie usunąć jedną "postać", ponieważ naprawdę ciężko jest powiedzieć, ile unicharów zajmuje ona.

Na szczęście NSString ma metodę, która pomaga w tym: -rangeOfComposedCharacterSequenceAtIndex:.Musisz pobrać indeks ostatniego unichara, uruchomić na nim tę metodę, a zwrócony NSRange poinformuje cię, skąd powinieneś usunąć. To coś takiego (nie testowane):

NSUInteger lastCharIndex = [myString length] - 1; // I assume string is not empty 
NSRange rangeOfLastChar = [myString rangeOfComposedCharacterSequenceAtIndex: lastCharIndex]; 
myNewString = [myString substringToIndex: rangeOfLastChar.location]; 
+0

+1 Właśnie tego szukałem. Działa to świetnie. ukryte głęboko w dokumentach, aby się dowiedzieć. –

0

Jeśli nie możesz uruchomić tego domyślnie, użyj bloku if/else i sprawdź, czy ostatni znak jest częścią znaku specjalnego. Jeśli tak, użyj podłańcucha do length-2, w przeciwnym razie użyj podłańcucha do length-1.

+0

Dzięki za odpowiedź! Ale czy nie byłoby to problemem, jeśli użytkownik wprowadzi znak z klawiatury, powiedz @/#/$ itd. Jeśli sprawdzę, czy ostatni znak jest znakiem specjalnym, byłoby to prawdą w tym przypadku, a my usunąć 2 znaki, skąd mieliśmy je usunąć? –

+0

Mam na myśli, w Twojej instrukcji if sprawdź, jakie znaki dają ci problemy. Nie te, które nie są. – Dustin

+0

O tak, ale niektóre, które dają mi problemy, istnieją w obu :) To jest sedno mojego problemu. –

0

Nie wiem dokładnie, na czym polega problem z długością znaków specjalnych.

Co proponuję to:

  • Store łańcuch długości do param przed dodaniem nowych znaków
  • Jeśli użytkownik wybierze Backspace (usunięcie ostatnich znaków), a następnie zdjąć łańcuch z ostatniej długości do nowej długości. Oznacza na przykład, że ostatnia zapisana długość łańcucha wynosi 5, a nowa długość łańcucha to 7, a następnie usuń nowy ciąg z indeksem od 0 do 4, więc przycina pozostałe znaki.

Jest to odwrotny sposób postępowania, ponieważ nie wiem dokładnie, jaki problem występuje wewnętrznie.

Ale domyślam się, że to rozwiązanie powinno działać.

Ciesz się kodowaniem :)

+0

Och Tak, to powinno działać, jak sądzę. Dziękuję za odpowiedź, ale wciąż nie rozumiem, jak rozwiązać ten problem z bardziej metodologicznym podejściem. Próbowałem różnych rzeczy, na przykład konwertowania go na NSData, a następnie usuwania bajtów, aby zobaczyć, co faktycznie się dzieje, ale bezskutecznie :( –

Powiązane problemy