Font Descriptor: ключові поняття та можливості дескриптора шрифту

Автор: IT Sectr Опубліковано: 2026-07-23 Час читання: 9 хв

Font Descriptor — це об’єкт UIFontDescriptor в iOS та NSFontDescriptor в macOS, який інкапсулює всі метадані шрифту: сімейство, накреслення, розмір, міжлітерний інтервал, міжрядковий інтервал та атрибути типографіки. Замість того щоб створювати шрифт безпосередньо через UIFont(name:size:), розробник описує бажані характеристики через дескриптор, а система підбирає найкращу відповідність із доступних шрифтів. За даними Apple Developer Documentation, UIFontDescriptor підтримує понад 20 атрибутів шрифту та використовується у всіх фреймворках типографіки iOS — від UIKit до Core Text та SwiftUI.

Головне

  • Font Descriptor — об’єкт-описувач шрифту, що містить метадані про сімейство, накреслення, розмір та атрибути типографіки
  • Дозволяє створювати UIFont із набору атрибутів без зазначення конкретної назви шрифту
  • Підтримує модифікацію існуючого шрифту: зміну розміру, накреслення, кернінгу без створення нового об’єкта
  • Використовується в UIKit, Core Text та SwiftUI для пошуку та налаштування шрифтів
  • Забезпечує шрифтовий матчинг — автоматичний підбір найближчого доступного накреслення

Що таке Font Descriptor та навіщо він потрібен

Font Descriptor — це об’єкт, який описує характеристики шрифту як набір пар ключ-значення, а не як конкретний файл шрифту. Замість створення шрифту за назвою розробник задає сімейство, накреслення, розмір та опціональні атрибути, а система підбирає найкращу відповідність. Такий підхід критичний для адаптивної типографіки: один і той самий дескриптор може працювати на різних версіях iOS, де набір доступних шрифтів відрізняється. Згідно з iOS Human Interface Guidelines, шрифтовий матчинг через дескриптори — рекомендований спосіб роботи з динамічними шрифтами.

Без Font Descriptor розробнику довелося б перевіряти доступність кожного шрифту за назвою та вручну визначати fallback-варіанти. Дескриптор автоматизує цей процес: він містить матрицю сумісності накреслень — нормальне, напівжирне, курсивне, напівжирний курсив — та за відсутності точного збігу повертає найближче доступне. Системний матчинг працює на рівні Core Text та доступний як на iOS, так і на macOS через єдиний NSFontDescriptor API.

Дескриптори також використовуються для користувацьких шрифтів — завантажених через Info.plist або доданих вручну. Якщо шрифт зареєстровано в системі, його дескриптор створюється так само, як для системного. Cross-platform нотатка: концепція дескриптора існує і в Android через Typeface.Builder, але iOS-реалізація через UIFontDescriptor дає значно більше атрибутів — понад 20 проти 5 в Android.

Основні властивості та атрибути Font Descriptor

UIFontDescriptor містить атрибути, згруповані в словник fontAttributes типу [UIFontDescriptor.AttributeName: Any]. Ключові атрибути включають сімейство шрифту (family), назву (name), розмір (size), накреслення (traits), матрицю трансформації (matrix), візуальний розмір (opticalSize) та текстовий стиль (textStyle). За даними Apple WWDC 2019 Session 227, використання текстових стилів — Dynamic Type — обов’язкове для accessibility-сумісних додатків.

Атрибут traits — це словник, що містить символьні характеристики: жирність (UIFontWeightTrait), курсивність (UIFontSlantTrait), ширина (UIFontWidthTrait) та інші. Ці значення використовуються шрифтовим матчером для підбору накреслення. Наприклад, UIFontWeightTrait зі значенням 0.0 — нормальне накреслення, 0.3 — напівжирне. Система автоматично мапить числові значення в доступні варіанти шрифту.

Додаткові атрибути включають featureSettings для OpenType-фіч (лігатури, кернінг, цифрові пропорції), visibleName для відображення користувачу, matrix для афінних трансформацій шрифту та cascadeList для каскадних списків fallback-шрифтів. Повний список атрибутів покриває практично всі сценарії типографіки в iOS та macOS.

АтрибутТипОпис
UIFontDescriptorFamilyStringСімейство шрифту (SF Pro, Helvetica Neue)
UIFontDescriptorNameStringПовна назва шрифту (HelveticaNeue-Bold)
UIFontDescriptorSizeNSNumberРозмір шрифту в пунктах
UIFontDescriptorMatrixNSValueАфінна матриця трансформації
UIFontDescriptorTraits[String: Any]Символьні характеристики накреслення
UIFontDescriptorTextStyleStringСтиль Dynamic Type (headline, body, caption)

Створення UIFont через Font Descriptor на Swift

Основний спосіб роботи з Font Descriptor в iOS — створення дескриптора з подальшою генерацією UIFont. Це кращий підхід, коли потрібно отримати шрифт з певними характеристиками, не знаючи точної назви. Процес складається з двох кроків: створення UIFontDescriptor через ініціалізатор та виклик методу font(withSize:) на дескрипторі.

swift
import UIKit

// Створити дескриптор шрифту для сімейства
let descriptor = UIFontDescriptor.init(
    fontAttributes: [
        .family: "SF Pro",
        .traits: [
            .weight: UIFont.Weight.bold
        ]
    ]
)

// Згенерувати UIFont з дескриптора
let font = descriptor.font(withSize: 17)

Цей підхід гарантує, що система підбере найкращу відповідність для напівжирного накреслення SF Pro на поточному пристрої. Ключова перевага — код не залежить від версії iOS: на iOS 13 буде використано SF Pro, на більш ранніх — Helvetica Neue або системний шрифт за замовчуванням.

Для створення шрифту з динамічним розміром використовується ініціалізатор зі стилем тексту та масштабом. Dynamic Type автоматично підлаштовує розмір під налаштування користувача:

swift
// Дескриптор Dynamic Type
let bodyDescriptor = UIFontDescriptor
    .preferredFontDescriptor(withTextStyle: .body)

// Зробити шрифт напівжирним
let boldDescriptor = bodyDescriptor.withSymbolicTraits([.traitBold])

// Згенерувати UIFont зі збереженням динамічного розміру
let boldBodyFont = UIFont(
    descriptor: boldDescriptor!,
    size: bodyDescriptor.pointSize
)

Важливо: метод withSymbolicTraits повертає опціональний дескриптор — якщо запитуване накреслення недоступне, повертається nil. Завжди перевіряйте опціонал перед використанням.

Модифікація атрибутів через додавання та заміну

Font Descriptor підтримує імутабельну модель — кожен метод модифікації повертає новий дескриптор зі зміненим атрибутом. Це відповідає value-семантиці та робить код передбачуваним: вихідний дескриптор ніколи не змінюється. Основні методи модифікації: addingAttributes для додавання атрибутів, withFace для зміни накреслення, withSize для зміни розміру, withMatrix для афінної трансформації.

Метод addingAttributes — найбільш гнучкий. Він приймає словник атрибутів та повертає новий дескриптор. При збігу ключів нові значення замінюють старі. Це дозволяє комбінувати зміни: додати вагу, змінити розмір та ввімкнути лігатури одним викликом. За даними Apple Technical Q&A QA1682, addingAttributes — рекомендований спосіб масової модифікації через розширення.

Практичне застосування: створення шрифту для моноширинного тексту в редакторі коду. Розробник бере системний моноширинний дескриптор, додає знижену вагу для тонких ліній та збільшує міжлітерний інтервал через featureSettings. Це дає більш читабельний код без завантаження окремого шрифту.

swift
let monoDescriptor = UIFontDescriptor.monospacedDigitFontDescriptor()

// Додати кастомні атрибути
let customDescriptor = monoDescriptor.addingAttributes([
    .size: 14,
    .traits: [
        .weight: UIFont.Weight.medium
    ]
])

let monoFont = UIFont(
    descriptor: customDescriptor,
    size: 14
)

Обмеження: не всі атрибути можна змінити після створення дескриптора. Наприклад, сімейство шрифту (family) задається один раз при ініціалізації. Якщо потрібно змінити сімейство, створюйте новий дескриптор. Це пов’язано з архітектурою Core Text, де дескриптор прив–9язаний до конкретного шрифтового ресурсу.

Шрифтовий матчинг та пошук системних шрифтів

Шрифтовий матчинг — ключова функція Font Descriptor, яка автоматично підбирає найкращу відповідність запитаним атрибутам серед встановлених шрифтів. Процес включає три етапи: фільтрація (відсів несумісних шрифтів), ранжування (сортування за ступенем відповідності) та вибір (повернення найкращого результату). Матчинг виконується на рівні Core Text — фреймворку, що лежить в основі всієї типографіки iOS.

Для пошуку всіх шрифтів, що відповідають дескриптору, використовується метод matchingFontDescriptors. Він повертає масив дескрипторів, відсортованих за релевантністю. Розробник може вибрати точний збіг (перший елемент) або перебрати варіанти для кастомної логіки. За даними Apple Font Handling Guide, це єдиний спосіб отримати список доступних накреслень для конкретного сімейства без перерахування за назвою.

Сценарій використання: при виборі шрифту в інтерфейсі налаштування тексту. Користувач вибирає сімейство, а додаток через matchingFontDescriptors отримує всі доступні накреслення та відображає їх у picker. Без матчингу довелося б жорстко кодувати список варіантів, який змінюється між версіями iOS.

swift
let searchDescriptor = UIFontDescriptor.init(
    fontAttributes: [.family: "SF Mono"]
)

// Отримати всі доступні накреслення
let matchingDescriptors = searchDescriptor
    .matchingFontDescriptors(withMandatoryKeys: nil)

for descriptor in matchingDescriptors {
    print(descriptor.object(forKey: .visibleName) ?? "unnamed")
}

Mandatory keys — параметр, що обмежує пошук. Якщо вказати [.family], матчинг поверне всі шрифти зазначеного сімейства. Якщо вказати [.family, .traits] — лише ті, що збігаються і за сімейством, і за накресленням. Використання mandatory keys прискорює матчинг при пошуку підмножини шрифтів.

Продуктивність: матчинг — синхронна операція, що займає від 0.5 до 5 мс на iOS. Для одиничного пошуку це непомітно, але при масовому переборі дескрипторів (наприклад, у picker з 50+ шрифтами) рекомендується кешувати результати. Apple рекомендує виконувати матчинг один раз при завантаженні екрану та зберігати масив дескрипторів.

Інтеграція з Core Text та CTFontDescriptor

Core Text — низькорівневий C-based фреймворк для роботи з типографікою на iOS та macOS. Його аналог UIFontDescriptor — CTFontDescriptor, який надає ті самі можливості на рівні Core Foundation. CTFontDescriptor використовується в Core Text API для створення шрифтів, вимірювання тексту та рендерингу складної типографіки. UIFontDescriptor по суті є Objective-C-обгорткою над CTFontDescriptor з розширеним набором атрибутів.

Toll-free bridging між UIFontDescriptor та CTFontDescriptor дозволяє передавати дескриптори між UIKit та Core Text без конвертації. Це критично для додатків, що використовують кастомний рендеринг тексту — наприклад, текстові редактори на основі TextKit або редактори коду з підсвічуванням синтаксису. Приклад: CTFontDescriptorCreateCopyWithAttribute створює копію дескриптора з доданим атрибутом — аналог addingAttributes з UIFontDescriptor.

Key attribute kCTFontURLAttribute в CTFontDescriptor містить URL шрифтового файлу. Це дозволяє визначити, чи є шрифт системним або користувацьким. Для кастомних шрифтів URL веде у файл шрифту (.ttf або .otf), для системних — у системну директорію шрифтів. Дані через дескриптор доступні лише для читання; зміна файлу шрифту через URL не підтримується.

Для просунутої типографіки — кастомні лігатури, контекстні заміни, альтернативні гліфи — використовується CTFontDescriptorCopyAttribute з ключем kCTFontFeatureSettingsAttribute. Цей атрибут містить масив словників OpenType-фіч, які можна додавати через дескриптор. За даними Apple Core Text Programming Guide, комбінування UIFontDescriptor з Core Text дає повний контроль над типографікою додатку.

Часто задавані питання

Чим Font Descriptor відрізняється від UIFont?

UIFont — це готовий до використання шрифт, який рендерить текст. Font Descriptor — це опис шрифту, набір атрибутів, з яких можна створити UIFont. Один дескриптор може породити безліч UIFont різних розмірів.

Чи можна використовувати Font Descriptor для кастомних шрифтів?

Так. Якщо шрифт зареєстровано в системі (через Info.plist або Core Graphics), його дескриптор створюється за сімейством або за назвою так само, як для системних шрифтів. Матчинг працює для будь-яких зареєстрованих шрифтів.

Як отримати назву шрифту з дескриптора?

Використовуйте descriptor.object(forKey: .visibleName), щоб отримати відображувану назву, або descriptor.postscriptName для PostScript-назви. PostScript-назва використовується при створенні шрифту через UIFont(name:size:).

Що таке cascade list в Font Descriptor?

Cascade list — це масив вкладених дескрипторів, які слугують fallback-шрифтами. Якщо основний шрифт не містить потрібний символ, система послідовно перевіряє шрифти з cascade list. Використовується для підтримки емодзі та CJK-символів.

Чи працює Font Descriptor в SwiftUI?

Так. SwiftUI підтримує Font Descriptor через Font(descriptor:size:). SwiftUI-обгортка приймає UIFontDescriptor та створює шрифт SwiftUI, зберігаючи всі атрибути дескриптора — кернінг, лігатури та накреслення.

Підсумки

  • Font Descriptor — об’єкт-описувач шрифту з атрибутами сімейства, накреслення, розміру та типографічних фіч
  • Дозволяє створювати UIFont з набору атрибутів з автоматичним шрифтовим матчингом
  • Підтримує імутабельну модифікацію через addingAttributes, withSize, withSymbolicTraits
  • matchingFontDescriptors повертає всі доступні накреслення для пошуку та вибору шрифтів
  • Інтегрується з Core Text через toll-free bridging між UIFontDescriptor та CTFontDescriptor
  • Підтримує Dynamic Type через бажані стилі тексту та масштабування
  • Рекомендується для адаптивної типографіки, що підтримує всі версії iOS без перевірки доступності шрифтів

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також