UIFont a CTFont — jsou třídy pro práci s fonty v iOS: UIFont z UIKit pro konfiguraci textu na vysoké úrovni v UILabel a UITextView, CTFont z Core Text pro vykreslování na nízké úrovni s plnou kontrolou nad glyfy a metrikami. Podle Apple Developer Documentation je UIFont používán v 90% standardních UI komponent, zatímco CTFont se aplikuje ve vlastních textových motorech a editorech. Obě třídy představují stejný font, ale na různé úrovni abstrakce.
Hlavní body
UIFont — je třída UIKit představující font pro zobrazení textu v UI komponentách: UILabel, UITextView, UITextField. Poskytuje jednoduché rozhraní pro získání systémových a vlastních fontů s určením velikosti, váhy a stylu. UIFont neumožňuje přímo spravovat kerning, ligatury a funkce OpenType — k tomu se používá Core Text.
CTFont — je typ Core Text (CTFontRef) poskytující přístup na nízké úrovni k datům fontu. CTFont pracuje přímo s Core Graphics pro vykreslování, podporuje všechny možnosti OpenType a TrueType, včetně alternativních glyfů, ligatur a variabilních fontů. CTFont je používán interně UIKit pro vykreslování UIFont, ale je také přímo dostupný pro vlastní kreslení.
UIFont a CTFont podporují toll-free bridging — konverzi mezi typy bez dodatečných nákladů. Casting UIFont as CTFont nebo CTFont as UIFont je možný ve Swift a Objective-C. To umožňuje používat API UIKit na vysoké úrovni pro konfiguraci a Core Text na nízké úrovni pro vykreslování bez kopírování dat fontu.
Obě třídy používají UIFontDescriptor (UIKit) / CTFontDescriptor (Core Text) pro popis charakteristik fontu: jméno, velikost, váha, styl, transformační matice. Deskriptor je slovník atributů, který lze upravovat a vytvářet nové fonty na základě existujících. Například přidat traitItalic k deskriptoru a získat kurzivní verzi stejného fontu.
UIFont poskytuje několik továrních metod pro vytváření fontů. systemFont(ofSize:) vrací systémový font San Francisco (iOS) nebo Helvetica (starší verze). boldSystemFont, italicSystemFont — varianty s řezem. preferredFont(forTextStyle:) vrací font Dynamic Type pro daný styl: .headline, .body, .caption1, .footnote. Tyto fonty se automaticky škálují při změně nastavení velikosti textu v systému.
Pro načítání vlastních fontů se používá UIFont(name:size:) s PostScript jménem fontu. Font musí být předem přidán do Info.plist a zahrnut do bundle aplikace. Podle Apple se doporučuje používat UIFont pro všechny standardní UI komponenty a přejít na CTFont pouze v případě potřeby vlastního vykreslování.
Dynamic Type — adaptivní systém fontů zavedený v iOS 7. Uživatel vybírá preferovanou velikost textu v Nastavení — od velmi malé po velmi velkou. UIFont.preferredFont automaticky vrací font odpovídající velikosti. Pro správnou funkci musí všechny UILabel mít adjustsFontForContentSizeCategory = true. Dynamic Type je povinný pro kompatibilitu s přístupností.
UIFontDescriptor umožňuje upravovat atributy fontu bez vytváření nové instance od nuly. Metody addingAttributes(_:), withSymbolicTraits(_:), withFamily(_:) vracejí nový deskriptor s upravenými parametry. To je vhodné pro získávání variant fontu: přidat traitBold k systémovému fontu a získat tučnou verzi bez znalosti PostScript jména.
CTFont (CTFontRef) — je typ Core Text pro práci na nízké úrovni s fonty. Vytváří se funkcemi CTFontCreateWithName, CTFontCreateWithFontDescriptor, CTFontCreateCopyWithAttributes. Každá funkce vrací font s určeným rozhraním, velikostí a volitelnými atributy. CTFont se používá v Core Graphics pro vykreslování textu na vlastních UIView přes drawRect.
CTFont poskytuje přístup k metrikám nedostupným v UIFont: CTFontGetGlyphsForCharacters vrací pole glyfů pro dané znaky, CTFontGetAdvancesForGlyphs — šířku každého glyfu, CTFontGetBoundingBox — hranice glyfu. To je nezbytné pro stavbu vlastních rozvržení textu: sloupce, rotace, obtékání.
CTFontGetAscent, CTFontGetDescent, CTFontGetLeading vracejí vertikální metriky fontu. CTFontGetUnitsPerEm — počet jednotek na em-square, používá se pro výpočet proporcí. CTFontGetGlyphCount — celkový počet glyfů ve fontu. Tato data jsou kritická pro polygrafickou typografii a vlastní sazbu, kde je vyžadováno přesné umístění každého znaku.
CTFont podporuje funkce OpenType: CTFontCopyFeatures vrací slovník dostupných funkcí fontu (ligatury, alternativní znaky, kerning), CTFontEnableFeature aktivuje konkrétní volbu. Variabilní fonty (Variable Fonts) se konfigurují přes CTFontCopyVariation a CTFontCreateCopyWithVariation, umožňující měnit weight, width a slant v kontinuálním rozsahu.
Vytvoření UIFont ve Swift se provádí prostřednictvím jedné z továrních metod nebo přímé inicializace podle jména. Nejčastější metodou je systemFont(ofSize:weight:) pro systémové fonty nebo preferredFont(forTextStyle:) pro Dynamic Type. Pro vlastní fonty se používá UIFont(name:size:) s uvedením PostScript jména.
UIFont.systemFont(ofSize:weight:) přijímá UIFont.Weight — od .ultraLight po .black. Tato metoda vrací systémový font San Francisco s odpovídající váhou. UIFont.monospacedSystemFont, UIFont.monospacedDigitSystemFont vracejí neproporcionální fonty pro kód a čísla. Všechny systémové fonty automaticky podporují 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
Každý font lze přímo přiřadit vlastnosti font UILabel nebo použít v NSAttributedString přes NSFontAttributeName. Systémové fonty jsou ukládány do mezipaměti iOS, proto opakované vytváření systémového fontu nepřináší dodatečné náklady.
Pro použití vlastního fontu přidejte soubor TTF nebo OTF do bundle projektu a uveďte jej v Info.plist (UIAppFonts). PostScript jméno fontu lze zjistit přes UIFont.familyNames a UIFont.fontNames(forFamilyName:). Po registraci je font dostupný přes UIFont(name:size:) v libovolném místě aplikace.
// Získat všechna jména rodin fontů
for family in UIFont.familyNames {
let names = UIFont.fontNames(forFamilyName: family)
print("\(rodina): \(jména)")
}
// Načíst vlastní font
if let customFont = UIFont(name: "MyCustomFont-Regular", size: 18) {
label.font = customFont
}
Pokud je jméno fontu nesprávné, UIFont(name:size:) vrací nil. Doporučuje se předem vypsat všechna dostupná jména fontů přes UIFont.familyNames a UIFont.fontNames(forFamilyName:) během ladění, abyste se ujistili, že je font správně zaregistrován.
Načítání vlastních fontů je možné dvěma způsoby: statická registrace přes Info.plist (UIAppFonts) a dynamická registrace přes CTFontManagerRegisterGraphicsFont. První způsob je jednodušší — font je dostupný ihned po spuštění aplikace. Druhý se používá pro fonty načítané ze sítě nebo stahované na vyžádání.
Dynamická registrace je užitečná pro zdroje na vyžádání: pokud aplikace obsahuje 20+ fontů, nemusí být všechny zahrnuty do počátečního bundle, ale lze je stáhnout při prvním použití. CTFontManagerRegisterFontsForURLs registruje fonty z uvedených URL. Po registraci je font dostupný přes UIFont(name:size:) jako obvykle.
Pro vlastní vykreslování přes Core Text použijte CTFontCreateWithName s PostScript jménem fontu. Rozdíl oproti UIFont je v tom, že CTFont lze vytvořit s transformační maticí (CTFontCreateWithNameAndOptions) — pro vytváření deformovaných fontů: naklánění, škálování na ose X, otáčení. To není v UIFont dostupné bez použití afinních transformací.
// Vytvořit CTFont s maticí zkosení
var matrix = CGAffineTransform(a: 1, b: 0, c: 0.2, d: 1, tx: 0, ty: 0)
let ctFont = CTFontCreateWithName(
"Helvetica" as CFString,
24, &matrix)
// Použít toll-free bridging s UIFont
let uiFont = ctFont as UIFont
label.font = uiFont
Transformační matice umožňuje vytvářet italic varianty bez samostatného souboru fontu. Parametr c (skew) přidává znakům náklon. Matice také umožňuje horizontální škálování fontu — vytváření stlačených nebo rozšířených variant stejného fontu.
Hlavní rozdíl mezi UIFont a CTFont je úroveň abstrakce. UIFont poskytuje jednoduché API pro běžné úkoly: získat systémový font, změnit velikost, aplikovat na UILabel. CTFont dává plnou kontrolu nad fontem: přístup ke glyfům, metrikám, tabulkám OpenType a variabilním osám. Volba závisí na úkolu.
| Vlastnost | UIFont | CTFont |
|---|---|---|
| Framework | UIKit | Core Text |
| Vytvoření | systemFont / preferredFont / initWithName | CTFontCreateWithName / CTFontCreateWithDescriptor |
| Přístup ke glyfům | Ne | CTFontGetGlyphsForCharacters |
| Funkce OpenType | Omezený (UIFontDescriptor) | Plný přístup |
| Variabilní fonty | Přes UIFontDescriptor | CTFontCopyVariation / CreateCopyWithVariation |
| Vykreslování | Automatické v UI komponentách | Core Graphics, vlastní |
Pro 95% úkolů vývoje pro iOS stačí UIFont. Core Text s CTFont je opodstatněný při vytváření textových editorů, PDF generátorů, knih s typografickou sazbou nebo aplikací s vlastním zobrazením vzácných jazyků.
Práce s fonty v iOS vyžaduje zohlednění výkonu. Každý unikátní font se při prvním použití načte do paměti a zabírá zdroje. Systémové fonty San Francisco jsou přednačtené a nevytvářejí dodatečné náklady. Vlastní fonty se načítají ze souboru a po prvním načtení jsou ukládány do mezipaměti systémem.
Doporučuje se omezit počet unikátních fontů v aplikaci na 3–5 rodin. Každý font zabírá od 50 KB do 2 MB v paměti. Používání různých vah jedné rodiny (regular, bold, medium) je efektivnější než načítání několika různých rodin.
Systém ukládá do mezipaměti vytvořené instance UIFont, proto opakovaná volání UIFont.systemFont(ofSize: 16, weight: .regular) nevytvářejí nový objekt. Nicméně UIFont(name:size:) pro vlastní fonty není vždy ukládán do mezipaměti — doporučuje se ukládat často používané fonty do statických vlastností nebo mezipaměti NSCache, aby se zabránilo opakovanému načítání ze souboru.
Při dynamické registraci fontů přes CTFontManagerRegisterGraphicsFont může být proces asynchronní, pokud je soubor fontu stahován ze sítě. V tomto případě by UILabel nebo UITextView měly zobrazovat záložní systémový font až do dokončení načítání. Po registraci se font stane dostupným a obrazovka automaticky aktualizuje zobrazení textu.
Často kladené otázky
Ano, UIFont a CTFont podporují toll-free bridging. Konverze se provádí jednoduchým castem: UIFont as CTFont nebo CTFont as UIFont. Nejsou žádné dodatečné náklady ani kopírování dat — obě třídy ukazují na stejný objekt fontu v paměti.
Pro všechny UI komponenty používejte UIFont. Je optimalizovaný pro UIKit, podporuje Dynamic Type, správně se škáluje při změně systémových nastavení. CTFont je opodstatněný pouze pro vlastní vykreslování přes Core Graphics nebo když je potřeba přístup k metrikám fontu na nízké úrovni.
Použijte UIFont.familyNames pro seznam rodin a UIFont.fontNames(forFamilyName:) pro PostScript jména. Volejte tento kód v režimu ladění a najděte požadovaný font. PostScript jméno obvykle obsahuje název rodiny a řez: „SFProText-Regular”, „HelveticaNeue-Bold”.
Ano, přes UIFontDescriptor lze nakonfigurovat variabilní osy: weight, width, slant. Nicméně API UIFont pro variabilní fonty je omezené ve srovnání s CTFontCopyVariation. Pro plnou kontrolu nad variabilními osami použijte Core Text a CTFontCreateCopyWithVariation.
Vytvořte statický slovník nebo NSCache s klíčem z kombinace jména a velikosti. Pro systémové fonty iOS ukládá instance do mezipaměti automaticky, ale pro vlastní fonty vytvořené přes UIFont(name:size:) se doporučuje ukládat objekty do mezipaměti aplikace, aby se zabránilo opakovanému načítání ze souboru TTF.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také