Основы Swift / 6.6. Строки и символы 3 - Unicode


Видео


"Я верила Тебе, тупица"
Данный раздел можно рассматривать не особо внимательно в первый раз. Возможно символы Юникода не пригодятся Вам, если Ваше приложение имеет лишь локализацию в кириллице. Однако всегда нужно стремиться вперёд и быть готовыми к локализации на другие языки, поэтому в дальнейшем обязательно рассмотрите этот раздел.
Юникод
Юникод - это интернациональный стандарт для кодирования, представления и обработки текста в различных письменных системах. Он позволяет Вам представить почти любой символ из любого языка в стандартизированной форме, а также читать и писать те символы в и из внешнего источника, как например из текстового файла или веб-страницы. Типы String и Character в Swift полностью Юникод-совместимы.
Юникод-скаляры
За кулисами нативный для Swift тип String построен из значений Юникод-скаляров. Юникод-скаляр - это уникальное 21-битовое число для символа или модификатора, например, U+0061 для LATIN SMALL LETTER A ("a") или U+1F425 для FRONT-FACING BABY CHICK ("🐥").

Юникод-скаляр - это любой код Юникод в диапазоне от U+0000 до U+D7FF включительно или от U+E000 до U+10FFFF включительно. Юникод-скаляры не включают коды Юникод суррогатных пар, которые являются кодами в промежутке от U+D800 до U+DFFF включительно.

Отметьте, что не все 21-битовые юникод-скаляры можно присвоить символу - некоторые скаляры зарезервированы для будущего использования. Скаляры, которые присунуты символу обычно имеют имя, как например LATIN SMALL LETTER A и FRONT-FACING BABY CHICK в примере выше.
Специальные символы в строковых литералах
Строковые литералы могут содержать следующие специальные символы:
  • Экранированные специальные символы \0 (нулевой символ), \\ (обратные слэш), \t (горизонтальная табуляция), \n (смена строки), \r (возврат каретки), \" (двойная кавычка) и \’ (одинарная кавычка)
  • Обыкновенный Юникод-скаляр, записываемый как \u{n}, где n - это 1-8 значное шестнадцатиричное число со значением, равным корректному коду Юникод\
@{6.6\1}
let wiseWords = "\"Воображение важнее знания\" - Энштейн" // "оображение важнее знания" - Энштейн
let dollarSign = "\u{24}" // $, Юникод-скаляр U+0024
let blackHeart = "\u{2665}" // ♥, Юникод-скаляр U+2665
let sparklingHeart = "\u{1F496}" // 💖, Юникод-скаляр U+1F496
Код демонстрирует четыре примера этих специальных символов. Константа wiseWords содержит две экранированные двойные кавычки. Константы dollarSign, blackHeart и sparklingHeart демонстрируют формат Юникод-скаляров.
Расширенные графем-кластеры
Каждый экземпляр типа Character репрезентует отдельный расширенный графем-кластер. Графем-класьер - это последовательность из одного или нескольких Юникод-скаляров, которые (после соединения) образуют единый человекочитаемый символ.
@{6.6\2}
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e с последующим  ́
// eAcute равен é, combinedEAcute равен é
Вот пример. Буква é может быть представлена в качестве одного Юникод-скаляра é (LATIN SMALL LETTER E WITH ACUTE или U+00E9). Однако эта же самая буква может быть представлена в качестве пары скаляров - обычная буква e (LATIN SMALL LETTER E или U+0065), которая сопровождается COMBINING ACUTE ACCENT скаляром (U+0301). COMBINING ACUTE ACCENT скаляр применяется графически к предшествующему ему скаляру, превращая e в é, когда происходит рендеринг системой Юникода.

В обоих случаях буква é представлен одним Character типа Swift, что представляется с помощью расширенного графем-кластера. В первом случае кластера содержит единственный скаляр, а во втором - кластер состоит из двух скаляров.
Предназначение
Расширенные графем-кластеры - это гибкий способ представить множество сложных печатных символов в качестве одного значения типа Character. Например, Hangul звуки из Корейского алфавита могут быть представлены в качестве заранее заданных или разложенных последовательностей. Оба этих представления будут считаться одним значением типа Character в Swift.
@{6.6\3}
let precomposed: Character = "\u{D55C}"
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}"
//precomposed равен "한", decomposed равен "한"
Предназначение 2
Расширенные графем-кластеры позволяют скалярам для включающих символов (таких как например COMBINING ENCLOSING CIRCLE или U+20DD) для включения других Юникод скаляров в качестве части одного значения типа Character.
@{6.6\4}
let enclosedEAcute: Character = "\u{E9}\u{20DD}"
// enclosedEAcute равен é⃝
Предназначение 3
Юникод-скаляры для символов индикации регионов могут быть объединены в пары для создания единого значения типа Character, как например комбинация REGIONAL SYMBOL LETTER R (U+1F1F7) и REGIONAL INDICATOR LETTER U (U+1F1FA).
@{6.6\5}
let regionalIndicatorForRussia: Character = "\u{1F1F7}\u{1F1FA}"
// regionalIndicatorForRussia равен 🇷🇺
Подсчёт символов
Чтобы получить значение количества символов в строке, используйте свойство count строки:
@{6.6\6}
let unusualMenagerie = "Коала 🐨, Улитка 🐌, Пингвин 🐧, Верблюд 🐫"
print("unusualMenagerie имеет \(unusualMenagerie.characters.count) символов")
// Напечатает "unusualMenagerie имеет 40 символов"
Расширенные графем-кластеры и подсчёт символов
Заметьте, что Swift-использование расширенных графем-кластеров для значения типа Character подразумевает, что строковая конкатенация или модификация не всегда может изменить количество символов в строке.
@{6.6\7}
var word = "cafe"
print("количество символов в \(word) равно \(word.characters.count)")
// Выведет "количество символов в cafe равно 4"
word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301
print("количество символов в \(word) равно \(word.characters.count)")
// Выведет "количество символов в café равно 4"
Например, если Вы зададите новую строку с помощью четырёхсимволоного слова cafe, а затем прибавите COMBINING ACUTE ACCENT (U+0301) в конец строки, то результирующая строка будет иметь количество символов, равное 4, причём четвёртым символом будет é, а не e.
Расширенные графем-кластеры и количество символов
Расширенные графем-кластеры могут быть составлены из нескольких Юникод-скаляров. Это означает, что различных символы и различные представления одного и того же символа могут требовать различное количество памяти для хранения. Ввиду этого символы в Swift в строковом представлении не занимают одного и того же количества памяти. В результате количество символов в строке не может быть вычислено без интегрирования через всю строку для определения границ их расширенных графем-кластеров. Если Вы работаете с особенно длинными строковыми значениями, то будьте острожны, так как count-свойство обязательно проитерируется через Юникод-скаляры во всей строке для определения символов этой строки.

Количество символов, возвращаемых свойством count, не всегда одинаково со свойством length типа NSString, даже если она содержит те же символы. Длина NSString основана на количестве 16-битных кодов символов в UTF-16 представлении строки, а не на количестве расширенных графем-кластеров в строке.