Как удалить последний символ Unicode из NSString

Я применил пользовательскую клавиатуру, связанную с текстовым полем, поэтому, когда пользователь нажимает кнопку удаления, я удаляю последний символ из строки и вручную обновляю текст текущего текстового поля.

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

Пока все хорошо.

Теперь проблема заключается в том, что пользователь имеет возможность вводить некоторые специальные символы Unicode, это не 1 байт, они также могут быть 2 байта, теперь при нажатии кнопки удаления мне нужно удалить весь символ, но если я следую описанному выше подходу, пользователю необходимо дважды нажать кнопку удаления.

Здесь, если я это сделаю:

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

он работает нормально, но тогда нормальные символы, которые всего 1 байт, удаляются дважды за раз.

Как обрабатывать такие сценарии?

Спасибо заранее.

EDIT:

Странно, что если я переключусь на клавиатуру iPhone, он будет обрабатывать оба случая соответствующим образом. Должен быть какой-то способ сделать это, есть что-то, чего я не хватает, но не могу понять, что.

Ответ 1

Здесь проблема. NSStrings кодируются с использованием UTF-16. Многие обычные символы Unicode занимают только один unichar (16-битное значение без знака). Тем не менее, некоторые глифы занимают два unichars. Хуже того, некоторые глифы могут быть составлены или разложены, например, это может быть одна кодовая точка Unicode или две - резкий акцент, за которым следует буква e. Это делает довольно трудным выполнение того, что вы хотите, а именно удаление одного "персонажа", потому что действительно сложно определить, сколько у него занимает unichars.

К счастью, в NSString есть метод, который помогает с этим: -rangeOfComposedCharacterSequenceAtIndex:. Что вам нужно сделать, это получить индекс последнего unichar, запустить этот метод для него, и возвращенный NSRange скажет вам, откуда удалить. Это происходит примерно так (не проверено):

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

Ответ 2

Если вы не можете заставить это работать по умолчанию, используйте блок if/else и проверьте, является ли последний символ частью специального символа. Если это так, используйте подстроку в length-2, в противном случае используйте подстроку в length-1.

Ответ 3

Я точно не знаю, в чем проблема с длиной байта специальных символов.

Что я предлагаю:

  • Сохранять длину строки до параметра, перед добавлением новых символов
  • Если пользователь выбирает backspace (удалить последние символы), удалите строку с последней длины на новую длину. Например, последняя сохраненная длина строки равна 5, а длина новой строки равна 7, а затем удаляет новую строку с индексом от 0 до 4, поэтому она обрезает оставшиеся символы.

Это наоборот, потому что я не знаю, в чем проблема, внутренне.

Но я думаю, логически это решение должно работать.

Наслаждайтесь кодированием:)