Вы рассматриваете строку в юникоде как последовательность байтов.Кодовые точки Unicode, кроме младшего UTF8, могут быть многобайтовыми, поэтому вы меняете стиль текста, удаляя части, отвечающие за ударение над буквой, как эта часть: https://www.compart.com/en/unicode/U+0301
UTF8 - это переменная ширина, поэтому путем обработкив качестве необработанных байтов вы можете получить странные результаты, я бы предложил использовать нечто, более осведомленное о юникоде, такое как ICU ( Международные компоненты для Юникода ).
Теперь представьте, что у вас есть двухбайтовая последовательностьвот так (это может быть не на 100% точно, но это иллюстрирует мою точку зрения):
0x056 0x000
e NUL
Теперь у вас есть строка UTF8 с 1 кодовой точкой и нулевым терминатором.Теперь скажите, что хотите добавить акцент к этому e
.Как бы Вы это сделали?Вы можете использовать специальный код Unicode для изменения e
, поэтому теперь строка выглядит так:
0x056 0x0CC 0x810 0x000
e U+0301 NUL
Где U+0301
- это 2-байтовый управляющий символ (Combining Acute Accent) и делает акцент e
.
Редактировать: Ответ предполагает кодировку UTF8, что, скорее всего, неверное предположение, но я думаю, что ответ, будь то UTF8 или UTF16, или любой другой тип кодировки с управляющими символами,иллюстрирует, почему у вас могут быть таинственные исчезающие акценты.Хотя это может быть UTF16, для простоты давайте представим, что мы живем в мире, где жизнь немного лучше, потому что все используют только UTF8, а UTF16 не существует.
Для ответа на комментарий (это связано не столько с вопросом, но с некоторыми забавными мелочами) и с некоторыми забавными подробностями о времени выполнения NS / CF / Swift и мостах, а также о константах CF и прочих забавных вещах, подобных этому: представление фактической строки в памяти реализация определена и может варьироваться (даже для постоянных строк, поверьте мне, я знаю, я исправил реализацию ELF в Clang для CoreFoundation несколько дней назад).В любом случае, вот некоторый код:
CF_INLINE CFStringEncoding __CFStringGetSystemEncoding(void) {
if (__CFDefaultSystemEncoding == kCFStringEncodingInvalidId) (void)CFStringGetSystemEncoding();
return __CFDefaultSystemEncoding;
}
CFStringEncoding CFStringFileSystemEncoding(void) {
if (__CFDefaultFileSystemEncoding == kCFStringEncodingInvalidId) {
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
__CFDefaultFileSystemEncoding = kCFStringEncodingUTF8;
#else
__CFDefaultFileSystemEncoding = CFStringGetSystemEncoding();
#endif
}
return __CFDefaultFileSystemEncoding;
}
В течение CoreFoundation / Foundation / SwiftFoundation (Да, вы никогда не знаете, какой тип NSString на самом деле тот, который вы держите, они обычно притворяются тем же, но подкапот в зависимости от того, как вы получили объект, который вы можете удерживать в одном из трех его вариантов).
Вот почему такой код существует, потому что строки NS / CF (Constant) / Swift имеют внутреннюю реализацию, определяемую реализациейпредставление.
if (((encoding & 0x0FFF) == kCFStringEncodingUnicode) && ((encoding == kCFStringEncodingUnicode) || ((encoding > kCFStringEncodingUTF8) && (encoding <= kCFStringEncodingUTF32LE)))) {
Если вы хотите согласованного поведения, вам нужно кодировать строку, используя определенную фиксированную кодировку, а не полагаться на внутреннее представление.