Attributed Text е механизъм на iOS SDK, представен от класовете NSAttributedString и NSMutableAttributedString, който позволява прилагането на множество стилове към различни части на един текстов низ. За разлика от обикновения NSString, Attributed String съхранява не само символи, но и речник от атрибути за всеки диапазон: шрифт, цвят, междуредие, сянка и подравняване. Според Apple Developer Documentation, Attributed String е основата за показване на форматиран текст в UILabel, UITextView и UITextField. Това е стандартният начин за стилизиране на текст без WebKit или библиотеки на трети страни.
Основни точки
NSAttributedString е клас от рамката Foundation, който представя низ с набор от именувани атрибути, свързани с диапазони от символи. Всеки атрибут е двойка ключ-стойност: ключът се дефинира от константа (NSFontAttributeName, NSForegroundColorAttributeName), а стойността от съответен обект (UIFont, UIColor). Атрибутите се прилагат към диапазон от символи чрез NSRange.
Класът е достъпен на всички платформи на Apple: iOS (2.0+), macOS, tvOS, watchOS. NSAttributedString е неизменим — след създаване атрибутите му са фиксирани. За динамична промяна се използва NSMutableAttributedString, който наследява NSAttributedString и добавя методите setAttributes, addAttributes, addAttribute, removeAttribute.
NSString е прост низ от символи без информация за стил. Всеки текст, предаден на UILabel чрез text, се показва с един шрифт, цвят и размер. NSAttributedString, предаден чрез attributedText, позволява на всеки символ да има собствен набор от атрибути. UILabel, UITextView и UITextField автоматично разпознават NSAttributedString и визуализират текста според атрибутите.
Вътрешно NSAttributedString съхранява NSString с текста и масив от диапазони на атрибути. Всеки диапазон е представен от структура NSRange и речник от атрибути. При визуализиране системата преминава през диапазоните и прилага съответните атрибути към всяка част. Ефективността зависи от броя на превключванията на атрибути — честите промени на кратки участъци увеличават времето за визуализация.
Атрибутите на NSAttributedString са константи, дефинирани в UIKit (iOS) и AppKit (macOS), всяка от които съответства на определен аспект от визуалното форматиране на текст. Всички атрибути са низове NSAttributedString.Key, а техните стойности са обекти от определени класове. Атрибутите се делят на символни (влияят на символи) и абзацни (влияят на абзаци).
Символните атрибути включват шрифт (NSFontAttributeName), цвят на текст (NSForegroundColorAttributeName), цвят на фон (NSBackgroundColorAttributeName), подчертаване (NSUnderlineStyleAttributeName), зачертаване (NSStrikethroughStyleAttributeName), сянка (NSShadowAttributeName). Абзацните атрибути се задават чрез NSParagraphStyleAttributeName, който контролира подравняването, отстъпите, междуредието и табулацията.
NSLinkAttributeName създава кликаема връзка в текста: стойността е URL или низ. UITextView автоматично обработва такива връзки, ако взаимодействието е включено. NSAttachmentAttributeName позволява вграждане на NSTextAttachment — изображение в текста, което се показва като inline елемент. Това се използва за създаване на текст с икони, емоджита или персонализирани изгледи вътре в низа.
Всеки атрибут на NSAttributedString има строго типизирана стойност. Нека разгледаме най-често използваните атрибути в iOS разработката. Шрифтът се задава от обект UIFont, цветът от UIColor, междуредието чрез NSMutableParagraphStyle, който позволява конфигуриране на подравняване, отстъпи и разстояния в един обект.
| Ключ на атрибут | Тип на стойност | Предназначение |
|---|---|---|
| NSFontAttributeName | UIFont | Шрифт на текста |
| NSForegroundColorAttributeName | UIColor | Цвят на текста |
| NSBackgroundColorAttributeName | UIColor | Цвят на фона под текста |
| NSUnderlineStyleAttributeName | NSNumber (Int) | Стил на подчертаване |
| NSParagraphStyleAttributeName | NSParagraphStyle | Настройки на абзац |
| NSKernAttributeName | NSNumber (Float) | Междубуквено разстояние |
NSParagraphStyle е контейнер за атрибути на абзац: alignment, lineSpacing, paragraphSpacing, firstLineHeadIndent, lineBreakMode, minimumLineHeight и други. За промяна на тези параметри се създава NSMutableParagraphStyle, настройват се желаните свойства и обектът се предава като стойност на атрибута NSParagraphStyleAttributeName. Това е единственият начин за управление на междуредието в NSAttributedString.
NSShadow позволява добавяне на сянка към текст: параметрите shadowOffset, shadowBlurRadius, shadowColor задават отместване, размазване и цвят на сянката. Атрибутите за подчертаване и зачертаване приемат комбинации от стилове: NSUnderlineStyle.single, .double, .thick, .patternDash, .patternDot. За прецизно управление на дебелината и цвета на линиите се използват NSUnderlineColorAttributeName и NSStrikethroughColorAttributeName.
Създаването на NSAttributedString в Swift се извършва чрез инициализатор с посочване на текст и речник от атрибути, или чрез NSMutableAttributedString с поетапно прилагане на стилове. Основният подход — дефиниране на речник от атрибути за целия текст, след което добавяне или промяна на атрибути за отделни диапазони.
Прост пример — задаване на шрифт, цвят и подравняване за целия низ. Речникът от атрибути се предава на инициализатора на NSAttributedString. Ключовете на речника са константи NSAttributedString.Key, стойностите са съответни UIKit обекти. Това е основният вариант, когато целият текст се форматира еднообразно.
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
Текстът ще се покаже с шрифт systemFont 16, тъмно сив цвят, центрирано подравняване и междуредие 4pt. Този подход е удобен за статични заглавия и бутони.
NSMutableAttributedString позволява прилагане на различни стилове към различни части на текста. Методът addAttribute добавя един атрибут към диапазон, addAttributes — речник от атрибути. Методът setAttributes заменя всички атрибути на диапазона с нови. Това е основният инструмент за създаване на текст с акценти.
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
Думата „1999“ ще бъде зелена и удебелена, останалият текст — стандартен. NSRange се изчислява ръчно — важно е правилно да се изчисли дължината в символи, особено при работа с емоджита и сложни Unicode символи.
NSMutableAttributedString предоставя методи за динамична промяна на текст и атрибути: append, insert, replace, delete, setAttributes, addAttribute, removeAttribute, enumerateAttributes. Това позволява изграждане на текст от различни източници, комбиниране на стилове и реагиране на събития от интерфейса.
За разлика от неизменимия NSAttributedString, mutable версията поддържа промяна на съдържанието без създаване на нов обект. Това е критично за текстови редактори, чатове и формуляри, където потребителят може да редактира текст, а стиловете трябва да се запазят.
В приложенията за съобщения всяко съобщение съдържа име на потребител (удебелен шрифт), текст на съобщението (нормален), време (сив цвят). NSMutableAttributedString позволява изграждане на такъв низ наведнъж, добавяйки частите в правилния ред със съответните атрибути.
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
Резултатът — един низ с три стилови части. Append автоматично изчислява правилно NSRange, позициите не трябва да се изчисляват ръчно. Този подход мащабира до произволен брой фрагменти.
Методът enumerateAttributes(in:options:using:) преминава през всички диапазони на атрибути в посочения интервал. Това е полезно за анализ на форматиране: намиране на всички връзки, промяна на цвета на определени атрибути или експорт на текст в HTML. В затварянето се предават речникът от атрибути и NSRange на текущата част.
Всички основни UI компоненти за показване на текст в UIKit поддържат NSAttributedString чрез свойството attributedText. UILabel показва статичен стилизиран текст, UITextView поддържа редактиране и връзки, UITextField приема атрибути отделно за placeholder и въведен текст.
UILabel е най-леката компонента за показване на стилизиран текст. Поддържа всички символни атрибути, но не обработва кликаеми връзки автоматично (за това е необходим UITextView). UILabel е идеален за заглавия, етикети и кратки текстове с форматиране.
UITextView обработва NSLinkAttributeName и показва връзките като интерактивни елементи. За активиране на тази функционалност задайте isSelectable = true и isEditable = false. При кликване на връзка делегатът получава извикване textView(_:shouldInteractWith:in:interaction:). UITextView също поддържа NSTextAttachment за изображения в текста.
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
След конфигуриране на isSelectable и isEditable, текстовата област се държи като статичен текстов блок, но връзките остават активни. Делегатът UITextViewDelegate управлява поведението при кликване.
Core Text е нискостепенна рамка на Apple за визуализиране на текст, която работи директно с NSAttributedString. За разлика от UIKit, Core Text не използва NSAttributedString директно като обект за показване, а го преобразува в CTFramesetter, след това в CTFrame и го визуализира в контекст на Core Graphics. Това дава пълен контрол върху разположението на редове и глифове.
Използването на Core Text е оправдано за персонализирани текстови оформления: колони, обтичане около изображения, завъртане на текст, нестандартни прекъсвания на редове. NSMutableParagraphStyle на Core Text включва атрибути, които не съществуват в UIKit: kCTParagraphStyleSpecifierMaximumLineSpacing, kCTParagraphStyleSpecifierLineBreakMode с допълнителни режими.
NSAttributedString се прехвърля безпроблемно между UIKit и Core Text, тъй като и двете рамки работят с един и същ тип. UIKit атрибутите (NSFontAttributeName, NSForegroundColorAttributeName) се разпознават автоматично от Core Text и обратно — Core Text атрибутите (kCTFontAttributeName) се четат от UIKit. Това позволява използването на UIKit за прости задачи и Core Text за персонализирано визуализиране на един и същ NSAttributedString обект.
Често задавани въпроси
NSString съхранява само текст без информация за стил. NSAttributedString допълва текста с речник от атрибути за всеки диапазон от символи. При предаване на UILabel чрез свойството text, NSString се показва като обикновен текст. При предаване на NSAttributedString чрез свойството attributedText, всички атрибути се прилагат: различни шрифтове, цветове и разстояния в един низ.
Използвайте метода addAttributes(_:range:) с речник от атрибути: addAttributes([.font: font, .foregroundColor: color], range: range). За добавяне или промяна на един атрибут използвайте addAttribute(_:value:range:). Методът setAttributes заменя всички съществуващи атрибути в диапазона с нови.
Създайте NSMutableParagraphStyle, задайте свойството lineSpacing, след което го предайте като стойност на атрибута NSParagraphStyleAttributeName. За пълен контрол са достъпни също minimumLineHeight, maximumLineHeight, paragraphSpacing, lineBreakMode и alignment. ParagraphStyle е единственият начин за управление на междуредието.
Да, SwiftUI поддържа NSAttributedString чрез Text(attributedString:) в iOS 15+. В по-старите версии използвайте UIViewRepresentable с UILabel или UITextView. SwiftUI също предоставя свой собствен тип AttributedString (SwiftUI, не Foundation) за декларативно форматиране с Markdown-подобен синтаксис.
Използвайте метода boundingRect(with:options:context:), който връща CGRect, необходим за показване на низа с дадените атрибути. Параметърът options: [.usesLineFragmentOrigin, .usesFontLeading] взема предвид междуредието и метриките на шрифта. За UILabel с ограничен брой редове използвайте sizeThatFits.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също