UIFont та CTFont — це класи для роботи зі шрифтами в iOS: UIFont із UIKit для високорівневого налаштування тексту в UILabel та UITextView, CTFont із Core Text для низькорівневого рендерингу з повним контролем над гліфами та метриками. За даними Apple Developer Documentation, UIFont використовується в 90% стандартних UI-компонентів, тоді як CTFont застосовується в кастомних текстових двигунах та редакторах. Обидва класи представляють один шрифт, але з різним рівнем абстракції.
Головне
UIFont — це клас UIKit, що представляє шрифт для відображення тексту в UI-компонентах: UILabel, UITextView, UITextField. Він надає простий інтерфейс для отримання системних та кастомних шрифтів із зазначенням розміру, ваги та стилю. UIFont не дозволяє безпосередньо керувати кернінгом, лігатурами та OpenType-фічами — для цього використовується Core Text.
CTFont — це тип Core Text (CTFontRef), що надає низькорівневий доступ до шрифтових даних. CTFont працює безпосередньо з Core Graphics для рендерингу, підтримує всі можливості OpenType та TrueType, включаючи альтернативні гліфи, лігатури та варіативні шрифти. CTFont використовується всередині UIKit для рендерингу UIFont, але також доступний безпосередньо для кастомного малювання.
UIFont та CTFont підтримують toll-free bridging — перетворення між типами без додаткових витрат. Кастинг UIFont as CTFont або CTFont as UIFont можливий у Swift та Objective-C. Це дозволяє використовувати високорівневий API UIKit для налаштування та низькорівневий Core Text для рендерингу без копіювання даних шрифту.
Обидва класи використовують UIFontDescriptor (UIKit) / CTFontDescriptor (Core Text) для опису характеристик шрифту: імені, розміру, ваги, стилю, матриці трансформації. Descriptor — це словник атрибутів, який можна модифікувати та створювати нові шрифти на основі існуючих. Наприклад, додати traitItalic до descriptor та отримати курсивну версію того ж шрифту.
UIFont надає кілька фабричних методів для створення шрифтів. systemFont(ofSize:) повертає системний шрифт San Francisco (iOS) або Helvetica (старі версії). boldSystemFont, italicSystemFont — варіанти з накресленням. preferredFont(forTextStyle:) повертає шрифт Dynamic Type для заданого стилю: .headline, .body, .caption1, .footnote. Ці шрифти автоматично масштабуються при зміні налаштувань розміру тексту в системі.
Для завантаження кастомних шрифтів використовується UIFont(name:size:) з PostScript-іменем шрифту. Шрифт має бути попередньо доданий до Info.plist та включений у bundle додатку. За даними Apple, рекомендується використовувати UIFont для всіх стандартних UI-компонентів та переходити на CTFont лише при необхідності кастомного рендерингу.
Dynamic Type — система адаптивних шрифтів, введена в iOS 7. Користувач вибирає бажаний розмір тексту в Налаштуваннях — від надмалого до надвеликого. UIFont.preferredFont автоматично повертає шрифт відповідного розміру. Для коректної роботи всі UILabel повинні мати adjustsFontForContentSizeCategory = true. Dynamic Type обов'язковий для accessibility-сумісності.
UIFontDescriptor дозволяє модифікувати атрибути шрифту без створення нового екземпляра з нуля. Методи addingAttributes(_:), withSymbolicTraits(_:), withFamily(_:) повертають новий descriptor із зміненими параметрами. Це зручно для отримання варіантів шрифту: додати traitBold до системного шрифту та отримати напівжирну версію, не знаючи PostScript-імені.
CTFont (CTFontRef) — це тип Core Text для низькорівневої роботи зі шрифтами. Він створюється функціями CTFontCreateWithName, CTFontCreateWithFontDescriptor, CTFontCreateCopyWithAttributes. Кожна функція повертає шрифт із зазначеним інтерфейсом, розміром та опціональними атрибутами. CTFont використовується в Core Graphics для рендерингу тексту на кастомних UIView через drawRect.
CTFont надає доступ до метрик, недоступних в UIFont: CTFontGetGlyphsForCharacters повертає масив гліфів для заданих символів, CTFontGetAdvancesForGlyphs — ширину кожного гліфа, CTFontGetBoundingBox — межі гліфа. Це необхідно для побудови кастомних текстових layout: колонок, обертання, обтікання.
CTFontGetAscent, CTFontGetDescent, CTFontGetLeading повертають вертикальні метрики шрифту. CTFontGetUnitsPerEm — кількість units на em-square, використовується для розрахунку пропорцій. CTFontGetGlyphCount — загальна кількість гліфів у шрифті. Ці дані критичні для поліграфічної типографіки та кастомних версток, де потрібне точне позиціонування кожного символу.
CTFont підтримує OpenType фічі: CTFontCopyFeatures повертає словник доступних функцій шрифту (лігатури, альтернативні символи, кернінг), CTFontEnableFeature активує конкретну опцію. Варіативні шрифти (Variable Fonts) налаштовуються через CTFontCopyVariation та CTFontCreateCopyWithVariation, дозволяючи змінювати weight, width та slant у безперервному діапазоні.
Створення UIFont у Swift виконується через один із фабричних методів або пряму ініціалізацію за ім'ям. Найпоширеніший спосіб — systemFont(ofSize:weight:) для системних шрифтів або preferredFont(forTextStyle:) для Dynamic Type. Для кастомних шрифтів використовується UIFont(name:size:) із зазначенням PostScript-імені.
UIFont.systemFont(ofSize:weight:) приймає UIFont.Weight — від .ultraLight до .black. Цей метод повертає системний шрифт San Francisco з відповідною вагою. UIFont.monospacedSystemFont, UIFont.monospacedDigitSystemFont повертають моноширинні шрифти для коду та чисел. Всі системні шрифти автоматично підтримують Dynamic Type.
let regularFont = UIFont.systemFont(ofSize: 16, weight: .regular)
let boldFont = UIFont.systemFont(ofSize: 16, weight: .bold)
let headlineFont = UIFont.preferredFont(forTextStyle: .headline)
let monoFont = UIFont.monospacedSystemFont(ofSize: 14, weight: .regular)
label.font = headlineFont
Кожен шрифт можна безпосередньо присвоїти властивості font UILabel або використовувати в NSAttributedString через NSFontAttributeName. Шрифти системи кешуються iOS, тому повторне створення системного шрифту не несе накладних витрат.
Для використання кастомного шрифту додайте файл TTF або OTF у bundle проекту та вкажіть його в Info.plist (UIAppFonts). PostScript-ім'я шрифту можна дізнатися через UIFont.familyNames та UIFont.fontNames(forFamilyName:). Після реєстрації шрифт доступний через UIFont(name:size:) у будь-якій точці додатку.
// Отримати всі назви сімейств шрифтів
for family in UIFont.familyNames {
let names = UIFont.fontNames(forFamilyName: family)
print("\(family): \(names)")
}
// Завантажити кастомний шрифт
if let customFont = UIFont(name: "MyCustomFont-Regular", size: 18) {
label.font = customFont
}
Якщо ім'я шрифту вказано невірно, UIFont(name:size:) повертає nil. Рекомендується заздалегідь вивести всі доступні імена шрифтів через UIFont.familyNames та UIFont.fontNames(forFamilyName:) під час налагодження, щоб переконатися, що шрифт зареєстровано коректно.
Завантаження кастомних шрифтів можливе двома способами: статична реєстрація через Info.plist (UIAppFonts) та динамічна реєстрація через CTFontManagerRegisterGraphicsFont. Перший спосіб простіший — шрифт доступний відразу після запуску додатку. Другий використовується для шрифтів, що завантажуються з мережі або за потреби.
Динамічна реєстрація корисна для on-demand ресурсів: якщо додаток містить 20+ шрифтів, усі їх можна не включати в initial bundle, а завантажити при першому використанні. CTFontManagerRegisterFontsForURLs реєструє шрифти із зазначених URL. Після реєстрації шрифт стає доступним через UIFont(name:size:) як зазвичай.
Для кастомного рендерингу через Core Text використовуйте CTFontCreateWithName з PostScript-іменем шрифту. Різниця з UIFont у тому, що CTFont може бути створений із матрицею трансформації (CTFontCreateWithNameAndOptions) — для створення викривлених шрифтів: нахил, масштаб по осі X, обертання. Це недоступно в UIFont без використання афінних трансформацій.
// Створити CTFont з матрицею нахилу
var matrix = CGAffineTransform(a: 1, b: 0, c: 0.2, d: 1, tx: 0, ty: 0)
let ctFont = CTFontCreateWithName(
"Helvetica" as CFString,
24, &matrix)
// Використати toll-free bridging з UIFont
let uiFont = ctFont as UIFont
label.font = uiFont
Матриця трансформації дозволяє створювати italic варіанти без окремого файлу шрифту. Параметр c (skew) додає нахил символам. Матриця також дозволяє масштабувати шрифт по горизонталі — створюючи стиснені або розширені варіанти одного шрифту.
Основна відмінність між UIFont та CTFont — рівень абстракції. UIFont надає простий API для поширених завдань: отримати системний шрифт, змінити розмір, застосувати до UILabel. CTFont дає повний контроль над шрифтом: доступ до гліфів, метрик, OpenType-таблиць та варіативних осей. Вибір залежить від завдання.
| Характеристика | UIFont | CTFont |
|---|---|---|
| Фреймворк | UIKit | Core Text |
| Створення | systemFont / preferredFont / initWithName | CTFontCreateWithName / CTFontCreateWithDescriptor |
| Доступ до гліфів | Ні | CTFontGetGlyphsForCharacters |
| OpenType фічі | Обмежений (UIFontDescriptor) | Повний доступ |
| Варіативні шрифти | Через UIFontDescriptor | CTFontCopyVariation / CreateCopyWithVariation |
| Рендеринг | Автоматично в UI-компонентах | Core Graphics, кастомний |
Для 95% завдань iOS-розробки достатньо UIFont. Core Text з CTFont виправданий при створенні текстових редакторів, PDF-генераторів, книг з типографською версткою або додатків з кастомним відображенням рідкісних мов.
Робота зі шрифтами в iOS потребує врахування продуктивності. Кожен унікальний шрифт завантажується в пам'ять при першому зверненні та займає ресурси. Системні шрифти San Francisco попередньо завантажені та не створюють накладних витрат. Кастомні шрифти завантажуються з файлу та кешуються системою після першого завантаження.
Рекомендується обмежувати кількість унікальних шрифтів у додатку до 3-5 сімейств. Кожен шрифт займає від 50 КБ до 2 МБ у пам'яті. Використання різних ваг одного сімейства (regular, bold, medium) ефективніше, ніж завантаження кількох різних сімейств.
Система кешує створені екземпляри UIFont, тому повторні виклики UIFont.systemFont(ofSize: 16, weight: .regular) не створюють новий об'єкт. Однак UIFont(name:size:) для кастомних шрифтів не завжди кешується — рекомендується зберігати часто використовувані шрифти в статичні властивості або кеш NSCache, щоб уникнути повторного завантаження з файлу.
При динамічній реєстрації шрифтів через CTFontManagerRegisterGraphicsFont процес може бути асинхронним, якщо файл шрифту завантажується з мережі. У цьому випадку UILabel або UITextView повинні відображати запасний системний шрифт до завершення завантаження. Після реєстрації шрифт стає доступним, і екран автоматично оновлює відображення тексту.
Часті запитання
Так, UIFont та CTFont підтримують toll-free bridging. Перетворення виконується простим кастингом: UIFont as CTFont або CTFont as UIFont. Жодних накладних витрат чи копіювання даних не відбувається — обидва класи вказують на один об'єкт шрифту в пам'яті.
Для всіх UI-компонентів використовуйте UIFont. Він оптимізований для UIKit, підтримує Dynamic Type, коректно масштабується при зміні системних налаштувань. CTFont виправданий лише для кастомного рендерингу через Core Graphics або при необхідності доступу до низькорівневих метрик шрифту.
Використовуйте UIFont.familyNames для списку сімейств та UIFont.fontNames(forFamilyName:) для PostScript-імен. Викличте цей код у debug-режимі та знайдіть потрібний шрифт. PostScript-ім'я зазвичай містить назву сімейства та накреслення: «SFProText-Regular», «HelveticaNeue-Bold».
Так, через UIFontDescriptor можна налаштувати варіативні осі: weight, width, slant. Однак API UIFont для варіативних шрифтів обмежений порівняно з CTFontCopyVariation. Для повного контролю над варіативними осями використовуйте Core Text та CTFontCreateCopyWithVariation.
Створіть статичний словник або NSCache з ключем із комбінації імені та розміру. Для системних шрифтів iOS кешує екземпляри автоматично, але для кастомних шрифтів, створених через UIFont(name:size:), рекомендується зберігати об'єкти в кеші додатку, щоб уникнути повторного завантаження з TTF-файлу.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також