Swift.String и Юникод
Если вас смущают отношения между строками Swift и их представлениями в Юникоде, эта статья для вас.
В C, C++, JavaScript можно легко получить целочисленный код заданной буквы и работать со строкой, как с массивом целых чисел. В некоторых алгоритмах может быть полезно представлять строку таким образом, но я не мог понять, как это сделать в Swift. Я ожидал чего-то вроде этого:
let helloString = "Hello" let eCode = helloString.codePoint(at: 1) // expected String method print("'e' =", eCode) // 'e' = 101
но в конце концов я закончил с этим:
Давайте разберемся с этим.
Юникод
Стандарт Unicode описывает более 137 000 символов и способы работы с ними. Проще говоря, Unicode определяет огромную таблицу различных символов:
каждый из которых имеет соответствующее целочисленное значение. Эти символы называются скалярами Unicode: между целочисленным кодом и символом или частью символа существует отношение один к одному.
Я бы не писал эту статью, если бы это были все определения стандарта Unicode. Существует также список правил обработки скаляров Unicode для получения символов, которых нет в таблице. Да, люди сгенерировали гораздо больше символов, чем может поместиться в таблице:
С таблицей и правилами объединения скаляров Unicode мы можем получить способ отразить любой символ в одно или несколько целочисленных значений. Для любого скалярного стандарта Unicode резервируется 21 бит для его кодирования. Наши компьютеры в основном работают с целыми числами длины: 8, 16, 32, … бит. Таким образом, стандарт Unicode также описывает, как кодировать строки Unicode целыми числами длиной 8 и 16 бит, определяя кодировки UTF-8 и UTF-16 соответственно.
Swift.String
Все проблемы в информатике можно решить на другом уровне косвенности, Дэвид Уилер
Строки Swift полностью поддерживают Unicode. Это означает, что строка «Флаг-🇺🇸» имеет длину (количество) 6 символов. Это особенно удобно, если вы когда-нибудь пытались получить количество символов в некоторых других языках — когда вы видите 6 символов и получаете длину 9!
Таким образом, тип Swift.String инкапсулирует всю сложность стандарта Unicode (не стесняйтесь открывать и читать). И это здорово, но как нам получить заветные целочисленные значения символов строки? Давайте рассмотрим отношения между различными типами вокруг типа String:
В листинге выше и на схеме в шапке статьи мы видим типы, разработанные инженерами Swift для соединения удобочитаемой String как массива символов и его целочисленных представлений при кодировании. Лучший способ познакомиться с ними поближе — прочитать официальную Документацию по Swift.String.
Вывод
То, что поначалу казалось мне неудобством при работе с типом Swift.String, теперь я вижу как правильный способ абстрагировать String как массив букв от его представления в разных кодировках.
- Строка представляет собой последовательность символов
- Каждый символ может быть закодирован одним или несколькими скалярами Unicode.
- Для каждого скаляра Unicode требуется максимум 21 бит, но существуют кодировки UTF-8 и UTF-16, разработанные для представления этих 21 бит в более коротких целочисленных типах.
- Swift.String и Swift.Character имеют свойство unicodeScalars для получения последовательности скаляров Unicode.
- Используя инициализатор массива с этим типом UnicodeScalarView, мы можем получить массив целых чисел UInt32, который кодирует данную строку.