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 разработчикът би трябвало да проверява наличността на всеки шрифт по име и ръчно да определя резервни варианти. Дескрипторът автоматизира този процес: той съдържа матрица за съвместимост на начертания — нормално, получерно, курсивно, получерно курсивно — и при липса на точно съвпадение връща най-близкото налично. Системно съвпадение работи на ниво Core Text и е достъпно както на iOS, така и на macOS чрез единен API NSFontDescriptor.

Дескрипторите се използват и за персонализирани шрифтове — заредени чрез Info.plist или добавени ръчно. Ако шрифтът е регистриран в системата, неговият дескриптор се създава точно както за системен шрифт. Междуплатформена бележка: концепцията за дескриптор съществува и в 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 — е задължително за приложения, съвместими с достъпност.

Атрибутът traits — е речник, съдържащ символни характеристики: дебелина (UIFontWeightTrait), курсив (UIFontSlantTrait), ширина (UIFontWidthTrait) и други. Тези стойности се използват от механизма за съвпадение на шрифтове за избор на начертание. Например UIFontWeightTrait със стойност 0.0 — нормално начертание, 0.3 — получерно. Системата автоматично преобразува числовите стойности в налични варианти на шрифта.

Допълнителните атрибути включват featureSettings за функции OpenType (лигатури, кернинг, пропорции на цифри), visibleName за показване на потребителя, matrix за афинни трансформации на шрифт и cascadeList за каскадни списъци с резервни шрифтове. Пълният списък с атрибути покрива почти всички сценарии за типография в 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 поддържа неизменим модел — всеки метод за модификация връща нов дескриптор с променен атрибут. Това съответства на семантика на стойност и прави кода предвидим: оригиналният дескриптор никога не се променя. Основните методи за модификация: addingAttributes за добавяне на атрибути, withFace за промяна на начертание, withSize за промяна на размер, withMatrix за афинна трансформация.

Методът addingAttributes — най-гъвкавият. Той приема речник с атрибути и връща нов дескриптор. При съвпадение на ключовете новите стойности заместват старите. Това позволява комбиниране на промени: добавяне на тегло, промяна на размер и активиране на лигатури с едно извикване. Според Apple Technical Q&A QA1682, addingAttributes е препоръчителният метод за масови модификации чрез разширение.

Практическо приложение: създаване на шрифт за моноширинен текст в редактор на код. Разработчикът взема системния monospace дескриптор, добавя намалено тегло за тънки линии и увеличава междубуквеното разстояние чрез 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, където дескрипторът е обвързан с конкретен ресурс на шрифт.

Съвпадение на шрифтове и търсене на системни шрифтове

Съвпадение на шрифтове — ключова функция на Font Descriptor, която автоматично избира най-доброто съответствие за заявените атрибути сред инсталираните шрифтове. Процесът включва три етапа: филтриране (отстраняване на несъвместими шрифтове), класиране (сортиране по степен на съответствие) и избор (връщане на най-добрия резултат). Съвпадението се изпълнява на ниво Core Text — рамката, която стои в основата на цялата типография на iOS.

За търсене на всички шрифтове, съответстващи на дескриптор, се използва методът matchingFontDescriptors. Той връща масив от дескриптори, сортирани по релевантност. Разработчикът може да избере точно съвпадение (първи елемент) или да прегледа вариантите за персонализирана логика. Според Apple Font Handling Guide, това е единственият начин да получите списък с налични начертания за конкретно семейство без изброяване по име.

Сценарий на използване: при избор на шрифт в интерфейса за настройки на текст. Потребителят избира семейство, а приложението чрез matchingFontDescriptors получава всички налични начертания и ги показва в избор. Без съвпадение би трябвало твърдо да кодирате списък с варианти, който се променя между версиите на 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 ms на iOS. За единично търсене това е незабележимо, но при масово преглеждане на дескриптори (например в избор с 50+ шрифта) се препоръчва кеширане на резултатите. Apple препоръчва да извършвате съвпадението веднъж при зареждане на екрана и да запазвате масива от дескриптори.

Интеграция с Core Text и CTFontDescriptor

Core Text — нисконивова C-базирана рамка за работа с типография на 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.

Ключов атрибут 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 — е масив от вложени дескриптори, които служат като резервни шрифтове. Ако основният шрифт не съдържа необходимия символ, системата последователно проверява шрифтовете от cascade list. Използва се за поддръжка на emoji и 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 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също