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

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

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

Все идет нормально.

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

Вот если я сделаю:

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

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

Как справиться с такими сценариями?

Заранее спасибо.

РЕДАКТИРОВАТЬ:

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

3 ответа

Решение

Здесь проблема. 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];

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

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

Я предлагаю следующее:

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

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

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

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

Другие вопросы по тегам