Attributed Text este un mecanism iOS SDK, reprezentat de clasele NSAttributedString și NSMutableAttributedString, care permite aplicarea mai multor stiluri la diferite porțiuni ale unui singur șir de text. Spre deosebire de NSString obișnuit, Attributed String stochează nu doar caracterele, ci și un dicționar de atribute pentru fiecare interval: font, culoare, spațiere între linii, umbră și aliniere. Conform Apple Developer Documentation, Attributed String stă la baza afișării textului formatat în UILabel, UITextView și UITextField. Este modul standard de stilizare a textului fără WebKit sau biblioteci terțe.
Puncte cheie
NSAttributedString este o clasă a framework-ului Foundation care reprezintă un șir cu un set de atribute denumite legate de intervale de caractere. Fiecare atribut este o pereche cheie-valoare: cheia este definită de o constantă (NSFontAttributeName, NSForegroundColorAttributeName), iar valoarea de un obiect corespunzător (UIFont, UIColor). Atributele sunt aplicate unui interval de caractere prin NSRange.
Clasa este disponibilă pe toate platformele Apple: iOS (2.0+), macOS, tvOS, watchOS. NSAttributedString este imutabil — după creare, atributele sale sunt fixe. Pentru modificare dinamică se utilizează NSMutableAttributedString, care moștenește NSAttributedString și adaugă metodele setAttributes, addAttributes, addAttribute, removeAttribute.
NSString este un simplu șir de caractere fără informații de stil. Orice text transmis către UILabel prin text este afișat cu un singur font, culoare și dimensiune. NSAttributedString transmis prin attributedText permite fiecărui caracter să aibă propriul set de atribute. UILabel, UITextView și UITextField recunosc automat NSAttributedString și redau textul conform atributelor.
Intern, NSAttributedString stochează un NSString cu textul și un tablou de intervale de atribute. Fiecare interval este reprezentat de o structură NSRange și un dicționar de atribute. La redare, sistemul parcurge intervalele și aplică atributele corespunzătoare fiecărei porțiuni. Eficiența depinde de numărul de comutări de atribute — schimbările frecvente pe porțiuni scurte cresc timpul de redare.
Atributele NSAttributedString sunt constante definite în UIKit (iOS) și AppKit (macOS), fiecare corespunzând unui aspect specific al formatării vizuale a textului. Toate atributele sunt șiruri NSAttributedString.Key, iar valorile lor sunt obiecte ale unor clase specifice. Atributele se împart în atribute de caracter (afectează caracterele) și atribute de paragraf (afectează paragrafele).
Atributele de caracter includ fontul (NSFontAttributeName), culoarea textului (NSForegroundColorAttributeName), culoarea fundalului (NSBackgroundColorAttributeName), sublinierea (NSUnderlineStyleAttributeName), tăierea (NSStrikethroughStyleAttributeName), umbra (NSShadowAttributeName). Atributele de paragraf se setează prin NSParagraphStyleAttributeName, care controlează alinierea, indentările, spațierea între linii și tabularea.
NSLinkAttributeName creează un link clickabil în text: valoarea este un URL sau un șir. UITextView procesează automat astfel de linkuri dacă interacțiunea este activată. NSAttachmentAttributeName permite încorporarea unui NSTextAttachment — o imagine în interiorul textului care este afișată ca element inline. Acesta este utilizat pentru a crea texte cu pictograme, emoji sau vizualizări personalizate în interiorul șirului.
Fiecare atribut NSAttributedString are o valoare strict tipizată. Să analizăm cele mai frecvent utilizate atribute în dezvoltarea iOS. Fontul se setează printr-un obiect UIFont, culoarea prin UIColor, spațierea între linii prin NSMutableParagraphStyle, care permite configurarea alinierii, indentărilor și spațierilor într-un singur obiect.
| Cheia atributului | Tipul valorii | Destinație |
|---|---|---|
| NSFontAttributeName | UIFont | Fontul textului |
| NSForegroundColorAttributeName | UIColor | Culoarea textului |
| NSBackgroundColorAttributeName | UIColor | Culoarea fundalului sub text |
| NSUnderlineStyleAttributeName | NSNumber (Int) | Stilul sublinierei |
| NSParagraphStyleAttributeName | NSParagraphStyle | Setări de paragraf |
| NSKernAttributeName | NSNumber (Float) | Spațierea între litere |
NSParagraphStyle este un container pentru atributele de paragraf: alignment, lineSpacing, paragraphSpacing, firstLineHeadIndent, lineBreakMode, minimumLineHeight și altele. Pentru a modifica acești parametri, se creează un NSMutableParagraphStyle, se configurează proprietățile dorite, iar obiectul se transmite ca valoare a atributului NSParagraphStyleAttributeName. Acesta este singurul mod de a controla spațierea între linii în NSAttributedString.
NSShadow permite adăugarea unei umbre textului: parametrii shadowOffset, shadowBlurRadius, shadowColor stabilesc deplasarea, estomparea și culoarea umbrei. Atributele de subliniere și tăiere acceptă combinații de stiluri: NSUnderlineStyle.single, .double, .thick, .patternDash, .patternDot. Pentru controlul precis al grosimii și culorii liniilor se utilizează NSUnderlineColorAttributeName și NSStrikethroughColorAttributeName.
Crearea unui NSAttributedString în Swift se realizează prin inițializator cu specificarea textului și a dicționarului de atribute, sau prin NSMutableAttributedString cu aplicarea treptată a stilurilor. Abordarea de bază — definirea unui dicționar de atribute pentru întregul text, apoi adăugarea sau modificarea atributelor pentru intervale individuale.
Un exemplu simplu — setarea fontului, culorii și alinierii pentru întregul șir. Dicționarul de atribute se transmite inițializatorului NSAttributedString. Cheile dicționarului sunt constante NSAttributedString.Key, valorile sunt obiecte UIKit corespunzătoare. Aceasta este varianta de bază când întregul text este formatat uniform.
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 16),
.foregroundColor: UIColor.darkGray,
.paragraphStyle: let style = NSMutableParagraphStyle()
style.alignment = .center
style.lineSpacing = 4
return style
]
let attributedString = NSAttributedString(
string: "Hello world",
attributes: attributes
)
label.attributedText = attributedString
Textul se va afișa cu fontul systemFont 16, culoare gri-închis, aliniere centrată și spațiere între linii de 4pt. Această abordare este convenabilă pentru titluri statice și butoane.
NSMutableAttributedString permite aplicarea de stiluri diferite la diferite porțiuni ale textului. Metoda addAttribute adaugă un singur atribut la un interval, addAttributes — un dicționar de atribute. Metoda setAttributes înlocuiește toate atributele intervalului cu altele noi. Acesta este instrumentul principal pentru crearea textului cu evidențieri.
let text = "Price: 1999 rubles"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.foregroundColor,
value: UIColor.green, range: NSRange(location: 6, length: 4))
attributed.addAttribute(.font,
value: UIFont.boldSystemFont(ofSize: 20), range: NSRange(location: 6, length: 4))
label.attributedText = attributed
Cuvântul „1999“ va fi verde și îngroșat, restul textului — standard. NSRange se calculează manual — este important să numărați corect lungimea în caractere, în special când lucrați cu emoji și caractere Unicode compuse.
NSMutableAttributedString oferă metode pentru modificarea dinamică a textului și atributelor: append, insert, replace, delete, setAttributes, addAttribute, removeAttribute, enumerateAttributes. Acest lucru permite construirea textului din surse diferite, combinarea stilurilor și reacționarea la evenimente de interfață.
Spre deosebire de NSAttributedString imutabil, versiunea mutabilă suportă modificarea conținutului fără a crea un obiect nou. Acest lucru este esențial pentru editori de text, chat-uri și formulare, unde utilizatorul poate edita textul, iar stilurile trebuie păstrate.
În aplicațiile de mesagerie, fiecare mesaj conține numele utilizatorului (font îngroșat), textul mesajului (normal), timpul (culoare gri). NSMutableAttributedString permite construirea unui astfel de șir dintr-o singură dată, adăugând părțile în ordinea corectă cu atributele corespunzătoare.
let result = NSMutableAttributedString()
let name = NSAttributedString(string: "Anna: ",
attributes: [.font: UIFont.boldSystemFont(ofSize: 15)])
let message = NSAttributedString(string: "Hello, how are you?",
attributes: [.font: UIFont.systemFont(ofSize: 15)])
let time = NSAttributedString(string: " 12:30",
attributes: [.foregroundColor: UIColor.gray])
result.append(name)
result.append(message)
result.append(time)
label.attributedText = result
Rezultatul — un singur șir cu trei porțiuni de stiluri diferite. Append calculează corect NSRange automat, pozițiile nu trebuie calculate manual. Această abordare se scalează la orice număr de fragmente.
Metoda enumerateAttributes(in:options:using:) parcurge toate intervalele de atribute în intervalul specificat. Acest lucru este util pentru analiza formatării: găsirea tuturor linkurilor, schimbarea culorii anumitor atribute sau exportul textului în HTML. În închidere se transmit dicționarul de atribute și NSRange al porțiunii curente.
Toate componentele UI de bază pentru afișarea textului în UIKit suportă NSAttributedString prin proprietatea attributedText. UILabel afișează text stilizat static, UITextView suportă editarea și linkurile, UITextField acceptă atribute separat pentru placeholder și textul introdus.
UILabel este cea mai ușoară componentă pentru afișarea textului stilizat. Suportă toate atributele de caracter, dar nu procesează linkurile clickabile automat (pentru aceasta este necesar UITextView). UILabel este ideal pentru titluri, etichete și texte scurte cu formatare.
UITextView procesează NSLinkAttributeName și afișează linkurile ca elemente interactive. Pentru a activa această funcționalitate, setați isSelectable = true și isEditable = false. La apăsarea unui link, delegatul primește apelul textView(_:shouldInteractWith:in:interaction:). UITextView suportă și NSTextAttachment pentru imagini în interiorul textului.
let text = "Details on developer.apple.com"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.link,
value: URL(string: "https://developer.apple.com")!,
range: NSRange(location: 0, length: text.count))
textView.attributedText = attributed
textView.isSelectable = true
textView.isEditable = false
După configurarea isSelectable și isEditable, zona de text se comportă ca un bloc de text static, dar linkurile rămân active. Delegatul UITextViewDelegate gestionează comportamentul la apăsare.
Core Text este un framework de nivel jos al Apple pentru randarea textului, care lucrează direct cu NSAttributedString. Spre deosebire de UIKit, Core Text nu utilizează NSAttributedString direct ca obiect de afișat, ci îl transformă în CTFramesetter, apoi în CTFrame și îl redează într-un context Core Graphics. Acest lucru oferă control complet asupra plasării liniilor și glifurilor.
Utilizarea Core Text se justifică pentru layout-uri personalizate de text: coloane, înfășurarea în jurul imaginilor, rotirea textului, întreruperi de linii nestandard. NSMutableParagraphStyle din Core Text include atribute care nu există în UIKit: kCTParagraphStyleSpecifierMaximumLineSpacing, kCTParagraphStyleSpecifierLineBreakMode cu moduri suplimentare.
NSAttributedString se transferă fără probleme între UIKit și Core Text, deoarece ambele framework-uri lucrează cu același tip. Atributele UIKit (NSFontAttributeName, NSForegroundColorAttributeName) sunt recunoscute automat de Core Text și invers — atributele Core Text (kCTFontAttributeName) sunt citite de UIKit. Acest lucru permite utilizarea UIKit pentru sarcini simple și Core Text pentru randare personalizată pe același obiect NSAttributedString.
Întrebări frecvente
NSString stochează doar textul fără informații de stil. NSAttributedString completează textul cu un dicționar de atribute pentru fiecare interval de caractere. La transmiterea către UILabel prin proprietatea text, NSString se afișează ca text simplu. La transmiterea NSAttributedString prin proprietatea attributedText, se aplică toate atributele: fonturi, culori și spațieri diferite într-un singur șir.
Utilizați metoda addAttributes(_:range:) cu un dicționar de atribute: addAttributes([.font: font, .foregroundColor: color], range: range). Pentru a adăuga sau modifica un singur atribut, utilizați addAttribute(_:value:range:). Metoda setAttributes înlocuiește toate atributele existente în interval cu cele noi.
Creați un NSMutableParagraphStyle, setați proprietatea lineSpacing, apoi transmiteți-l ca valoare a atributului NSParagraphStyleAttributeName. Pentru control complet, sunt disponibile și minimumLineHeight, maximumLineHeight, paragraphSpacing, lineBreakMode și alignment. ParagraphStyle este singurul mod de a controla spațierea între linii.
Da, SwiftUI suportă NSAttributedString prin Text(attributedString:) în iOS 15+. În versiunile mai vechi, utilizați UIViewRepresentable cu UILabel sau UITextView. SwiftUI oferă și propriul tip AttributedString (SwiftUI, nu Foundation) pentru formatare declarativă cu sintaxă asemănătoare Markdown.
Utilizați metoda boundingRect(with:options:context:), care returnează CGRect-ul necesar pentru afișarea șirului cu atributele specificate. Parametrul options: [.usesLineFragmentOrigin, .usesFontLeading] ia în considerare spațierile între linii și metricele fontului. Pentru UILabel cu număr limitat de linii, utilizați sizeThatFits.
Concluzii
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