Font Descriptor — це об’єкт UIFontDescriptor в iOS та NSFontDescriptor в macOS, який інкапсулює всі метадані шрифту: сімейство, накреслення, розмір, міжлітерний інтервал, міжрядковий інтервал та атрибути типографіки. Замість того щоб створювати шрифт безпосередньо через UIFont(name:size:), розробник описує бажані характеристики через дескриптор, а система підбирає найкращу відповідність із доступних шрифтів. За даними Apple Developer Documentation, UIFontDescriptor підтримує понад 20 атрибутів шрифту та використовується у всіх фреймворках типографіки iOS — від UIKit до Core Text та SwiftUI.
Головне
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.
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.
| Атрибут | Тип | Опис |
|---|---|---|
| UIFontDescriptorFamily | String | Сімейство шрифту (SF Pro, Helvetica Neue) |
| UIFontDescriptorName | String | Повна назва шрифту (HelveticaNeue-Bold) |
| UIFontDescriptorSize | NSNumber | Розмір шрифту в пунктах |
| UIFontDescriptorMatrix | NSValue | Афінна матриця трансформації |
| UIFontDescriptorTraits | [String: Any] | Символьні характеристики накреслення |
| UIFontDescriptorTextStyle | String | Стиль Dynamic Type (headline, body, caption) |
Основний спосіб роботи з Font Descriptor в iOS — створення дескриптора з подальшою генерацією UIFont. Це кращий підхід, коли потрібно отримати шрифт з певними характеристиками, не знаючи точної назви. Процес складається з двох кроків: створення UIFontDescriptor через ініціалізатор та виклик методу font(withSize:) на дескрипторі.
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 автоматично підлаштовує розмір під налаштування користувача:
// Дескриптор 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. Це дає більш читабельний код без завантаження окремого шрифту.
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.
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 — низькорівневий 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 дає повний контроль над типографікою додатку.
Часто задавані питання
UIFont — це готовий до використання шрифт, який рендерить текст. Font Descriptor — це опис шрифту, набір атрибутів, з яких можна створити UIFont. Один дескриптор може породити безліч UIFont різних розмірів.
Так. Якщо шрифт зареєстровано в системі (через Info.plist або Core Graphics), його дескриптор створюється за сімейством або за назвою так само, як для системних шрифтів. Матчинг працює для будь-яких зареєстрованих шрифтів.
Використовуйте descriptor.object(forKey: .visibleName), щоб отримати відображувану назву, або descriptor.postscriptName для PostScript-назви. PostScript-назва використовується при створенні шрифту через UIFont(name:size:).
Cascade list — це масив вкладених дескрипторів, які слугують fallback-шрифтами. Якщо основний шрифт не містить потрібний символ, система послідовно перевіряє шрифти з cascade list. Використовується для підтримки емодзі та CJK-символів.
Так. SwiftUI підтримує Font Descriptor через Font(descriptor:size:). SwiftUI-обгортка приймає UIFontDescriptor та створює шрифт SwiftUI, зберігаючи всі атрибути дескриптора — кернінг, лігатури та накреслення.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також