UIFont și CTFont — sunt clase pentru lucrul cu fonturile în iOS: UIFont din UIKit pentru configurarea de nivel înalt a textului în UILabel și UITextView, CTFont din Core Text pentru randarea de nivel scăzut cu control complet asupra glifelor și metricilor. Conform Apple Developer Documentation, UIFont este folosit în 90% din componentele UI standard, în timp ce CTFont este aplicat în motoarele de text personalizate și editoare. Ambele clase reprezintă același font, dar la niveluri diferite de abstractizare.
Principalele puncte
UIFont — este clasa UIKit care reprezintă un font pentru afișarea textului în componentele UI: UILabel, UITextView, UITextField. Oferă o interfață simplă pentru obținerea fonturilor de sistem și personalizate cu specificarea dimensiunii, greutății și stilului. UIFont nu permite gestionarea directă a kerningului, ligaturilor și funcțiilor OpenType — pentru aceasta se folosește Core Text.
CTFont — este un tip Core Text (CTFontRef) care oferă acces de nivel scăzut la datele fontului. CTFont lucrează direct cu Core Graphics pentru randare, suportă toate capacitățile OpenType și TrueType, inclusiv glife alternative, ligaturi și fonturi variabile. CTFont este folosit intern de UIKit pentru randarea UIFont, dar este disponibil și direct pentru desenarea personalizată.
UIFont și CTFont suportă toll-free bridging — conversia între tipuri fără costuri suplimentare. Castingul UIFont as CTFont sau CTFont as UIFont este posibil în Swift și Objective-C. Acest lucru permite utilizarea API-ului de nivel înalt UIKit pentru configurare și Core Text de nivel scăzut pentru randare fără copierea datelor fontului.
Ambele clase folosesc UIFontDescriptor (UIKit) / CTFontDescriptor (Core Text) pentru descrierea caracteristicilor fontului: nume, dimensiune, greutate, stil, matricea de transformare. Descriptorul este un dicționar de atribute care poate fi modificat pentru a crea fonturi noi pe baza celor existente. De exemplu, adăugarea traitItalic la descriptor pentru a obține versiunea cursivă a aceluiași font.
UIFont oferă mai multe metode fabrică pentru crearea fonturilor. systemFont(ofSize:) returnează fontul de sistem San Francisco (iOS) sau Helvetica (versiuni vechi). boldSystemFont, italicSystemFont — variante cu caractere. preferredFont(forTextStyle:) returnează fontul Dynamic Type pentru stilul dat: .headline, .body, .caption1, .footnote. Aceste fonturi se scalează automat la modificarea setărilor dimensiunii textului în sistem.
Pentru încărcarea fonturilor personalizate se folosește UIFont(name:size:) cu numele PostScript al fontului. Fontul trebuie adăugat în prealabil în Info.plist și inclus în bundle-ul aplicației. Conform Apple, se recomandă utilizarea UIFont pentru toate componentele UI standard și trecerea la CTFont doar când este necesară randarea personalizată.
Dynamic Type — sistemul de fonturi adaptive introdus în iOS 7. Utilizatorul alege dimensiunea preferată a textului în Setări — de la foarte mic la foarte mare. UIFont.preferredFont returnează automat fontul cu dimensiunea corespunzătoare. Pentru funcționarea corectă, toate UILabel-urile trebuie să aibă adjustsFontForContentSizeCategory = true. Dynamic Type este obligatoriu pentru conformitatea cu accesibilitatea.
UIFontDescriptor permite modificarea atributelor fontului fără a crea o nouă instanță de la zero. Metodele addingAttributes(_:), withSymbolicTraits(_:), withFamily(_:) returnează un nou descriptor cu parametrii modificați. Acest lucru este util pentru obținerea variantelor de font: adăugarea traitBold la fontul de sistem pentru a obține versiunea îngroșată fără a cunoaște numele PostScript.
CTFont (CTFontRef) — este un tip Core Text pentru lucrul de nivel scăzut cu fonturile. Se creează cu funcțiile CTFontCreateWithName, CTFontCreateWithFontDescriptor, CTFontCreateCopyWithAttributes. Fiecare funcție returnează un font cu interfața, dimensiunea și atributele opționale specificate. CTFont este folosit în Core Graphics pentru randarea textului pe UIView-uri personalizate prin drawRect.
CTFont oferă acces la metrici indisponibile în UIFont: CTFontGetGlyphsForCharacters returnează un array de glife pentru caracterele date, CTFontGetAdvancesForGlyphs — lățimea fiecărui glif, CTFontGetBoundingBox — limitele glifului. Acest lucru este necesar pentru construirea layout-urilor de text personalizate: coloane, rotire, încadrare.
CTFontGetAscent, CTFontGetDescent, CTFontGetLeading returnează metricile verticale ale fontului. CTFontGetUnitsPerEm — numărul de unități pe em-square, folosit pentru calcularea proporțiilor. CTFontGetGlyphCount — numărul total de glife în font. Aceste date sunt critice pentru tipografia poligrafică și machetele personalizate unde este necesară poziționarea precisă a fiecărui caracter.
CTFont suportă funcțiile OpenType: CTFontCopyFeatures returnează un dicționar al funcțiilor disponibile ale fontului (ligaturi, caractere alternative, kerning), CTFontEnableFeature activează o opțiune specifică. Fonturile variabile (Variable Fonts) se configurează prin CTFontCopyVariation și CTFontCreateCopyWithVariation, permițând modificarea weight, width și slant într-un interval continuu.
Crearea UIFont în Swift se realizează printr-una dintre metodele fabrică sau inițializarea directă după nume. Cea mai comună metodă este systemFont(ofSize:weight:) pentru fonturile de sistem sau preferredFont(forTextStyle:) pentru Dynamic Type. Pentru fonturile personalizate se folosește UIFont(name:size:) cu specificarea numelui PostScript.
UIFont.systemFont(ofSize:weight:) acceptă UIFont.Weight — de la .ultraLight la .black. Această metodă returnează fontul de sistem San Francisco cu greutatea corespunzătoare. UIFont.monospacedSystemFont, UIFont.monospacedDigitSystemFont returnează fonturi monospațiate pentru cod și numere. Toate fonturile de sistem suportă automat 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
Fiecare font poate fi atribuit direct proprietății font a UILabel sau folosit în NSAttributedString prin NSFontAttributeName. Fonturile de sistem sunt memorate în cache de iOS, deci crearea repetată a unui font de sistem nu implică costuri suplimentare.
Pentru a utiliza un font personalizat, adăugați fișierul TTF sau OTF în bundle-ul proiectului și specificați-l în Info.plist (UIAppFonts). Numele PostScript al fontului poate fi aflat prin UIFont.familyNames și UIFont.fontNames(forFamilyName:). După înregistrare, fontul este disponibil prin UIFont(name:size:) în orice punct al aplicației.
// Obține toate numele familiilor de fonturi
for family in UIFont.familyNames {
let names = UIFont.fontNames(forFamilyName: family)
print("\(familie): \(nume)")
}
// Încarcă font personalizat
if let customFont = UIFont(name: "MyCustomFont-Regular", size: 18) {
label.font = customFont
}
Dacă numele fontului este incorect, UIFont(name:size:) returnează nil. Se recomandă afișarea în prealabil a tuturor numelor disponibile ale fonturilor prin UIFont.familyNames și UIFont.fontNames(forFamilyName:) în timpul depanării pentru a vă asigura că fontul este înregistrat corect.
Încărcarea fonturilor personalizate este posibilă în două moduri: înregistrarea statică prin Info.plist (UIAppFonts) și înregistrarea dinamică prin CTFontManagerRegisterGraphicsFont. Prima metodă este mai simplă — fontul este disponibil imediat după pornirea aplicației. A doua este utilizată pentru fonturile încărcate din rețea sau descărcate la cerere.
Înregistrarea dinamică este utilă pentru resurse la cerere: dacă aplicația conține 20+ fonturi, nu este necesar să fie incluse toate în bundle-ul inițial, ci pot fi descărcate la prima utilizare. CTFontManagerRegisterFontsForURLs înregistrează fonturile din URL-urile specificate. După înregistrare, fontul devine disponibil prin UIFont(name:size:) ca de obicei.
Pentru randarea personalizată prin Core Text utilizați CTFontCreateWithName cu numele PostScript al fontului. Diferența față de UIFont este că CTFont poate fi creat cu o matrice de transformare (CTFontCreateWithNameAndOptions) — pentru a crea fonturi deformate: înclinare, scalare pe axa X, rotire. Acest lucru nu este disponibil în UIFont fără utilizarea transformărilor afine.
// Creează CTFont cu matrice de înclinare
var matrix = CGAffineTransform(a: 1, b: 0, c: 0.2, d: 1, tx: 0, ty: 0)
let ctFont = CTFontCreateWithName(
"Helvetica" as CFString,
24, &matrix)
// Folosește toll-free bridging cu UIFont
let uiFont = ctFont as UIFont
label.font = uiFont
Matricea de transformare permite crearea variantelor italic fără un fișier de font separat. Parametrul c (skew) adaugă înclinare caracterelor. Matricea permite, de asemenea, scalarea orizontală a fontului — creând variante comprimate sau extinse ale aceluiași font.
Diferența principală între UIFont și CTFont este nivelul de abstractizare. UIFont oferă un API simplu pentru sarcinile comune: obținerea fontului de sistem, schimbarea dimensiunii, aplicarea la UILabel. CTFont oferă control complet asupra fontului: acces la glife, metrici, tabele OpenType și axe variabile. Alegerea depinde de sarcină.
| Caracteristică | UIFont | CTFont |
|---|---|---|
| Framework | UIKit | Core Text |
| Creare | systemFont / preferredFont / initWithName | CTFontCreateWithName / CTFontCreateWithDescriptor |
| Acces la glife | Nu | CTFontGetGlyphsForCharacters |
| Funcții OpenType | Limitat (UIFontDescriptor) | Acces complet |
| Fonturi variabile | Prin UIFontDescriptor | CTFontCopyVariation / CreateCopyWithVariation |
| Randare | Automat în componentele UI | Core Graphics, personalizat |
Pentru 95% din sarcinile de dezvoltare iOS este suficient UIFont. Core Text cu CTFont este justificat la crearea editorilor de text, generatoarelor PDF, cărților cu machetare tipografică sau aplicațiilor cu afișare personalizată a limbilor rare.
Lucrul cu fonturile în iOS necesită luarea în considerare a performanței. Fiecare font unic este încărcat în memorie la prima utilizare și ocupă resurse. Fonturile de sistem San Francisco sunt preîncărcate și nu creează costuri suplimentare. Fonturile personalizate sunt încărcate din fișier și memorate în cache de sistem după prima încărcare.
Se recomandă limitarea numărului de fonturi unice în aplicație la 3-5 familii. Fiecare font ocupă de la 50 KB la 2 MB în memorie. Utilizarea diferitelor greutăți ale aceleiași familii (regular, bold, medium) este mai eficientă decât încărcarea mai multor familii diferite.
Sistemul memorează în cache instanțele create ale UIFont, deci apelurile repetate ale UIFont.systemFont(ofSize: 16, weight: .regular) nu creează un obiect nou. Cu toate acestea, UIFont(name:size:) pentru fonturile personalizate nu este întotdeauna memorat în cache — se recomandă salvarea fonturilor frecvent utilizate în proprietăți statice sau cache NSCache pentru a evita reîncărcarea din fișier.
La înregistrarea dinamică a fonturilor prin CTFontManagerRegisterGraphicsFont, procesul poate fi asincron dacă fișierul fontului este descărcat din rețea. În acest caz, UILabel sau UITextView trebuie să afișeze un font de sistem de rezervă până la finalizarea încărcării. După înregistrare, fontul devine disponibil, iar ecranul actualizează automat afișarea textului.
Întrebări frecvente
Da, UIFont și CTFont suportă toll-free bridging. Conversia se realizează printr-un simplu casting: UIFont as CTFont sau CTFont as UIFont. Nu există costuri suplimentare sau copiere de date — ambele clase indică același obiect font în memorie.
Pentru toate componentele UI utilizați UIFont. Este optimizat pentru UIKit, suportă Dynamic Type, se scalează corect la modificarea setărilor de sistem. CTFont este justificat doar pentru randarea personalizată prin Core Graphics sau când este necesar accesul la metricile de nivel scăzut ale fontului.
Utilizați UIFont.familyNames pentru lista familiilor și UIFont.fontNames(forFamilyName:) pentru numele PostScript. Apelați acest cod în modul de depanare și găsiți fontul dorit. Numele PostScript conține de obicei numele familiei și caracterul: „SFProText-Regular”, „HelveticaNeue-Bold”.
Da, prin UIFontDescriptor se pot configura axele variabile: weight, width, slant. Cu toate acestea, API-ul UIFont pentru fonturi variabile este limitat în comparație cu CTFontCopyVariation. Pentru control complet asupra axelor variabile utilizați Core Text și CTFontCreateCopyWithVariation.
Creați un dicționar static sau NSCache cu cheia din combinația numelui și dimensiunii. Pentru fonturile de sistem, iOS memorează în cache instanțele automat, dar pentru fonturile personalizate create prin UIFont(name:size:), se recomandă salvarea obiectelor în cache-ul aplicației pentru a evita reîncărcarea din fișierul TTF.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și