Attributed Text — це механізм iOS SDK, представлений класами NSAttributedString та NSMutableAttributedString, який дозволяє застосовувати множинні стилі до різних ділянок однієї текстової рядка. На відміну від звичайного NSString, Attributed String зберігає не лише символи, але й словник атрибутів для кожного діапазону: шрифт, колір, міжрядковий інтервал, тінь та вирівнювання. Згідно з Документацією розробника Apple, 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 — зображення всередині тексту, яке відображається як інлайновий елемент. Це використовується для створення тексту з іконками, емодзі або користувацькими відженнями всередині рядка.
Кожен атрибут 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, змінна версія підтримує зміну вмісту без створення нового об’єкта. Це критично для текстових редакторів, чатів та форм, де користувач може редагувати текст, а стилі повинні зберігатися.
В месенджерах кожен повідомлення містить ім’я користувача (напівжирний шрифт), текст повідомлення (звичайний), час (сірий колір). 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 приймає атрибути окремо для підказки та введеного тексту.
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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також