Как создать атрибутивную строку (NSAttributedString) в Swift для UILabel?
Создание атрибутивных строк в Swift
Вы правы: UILabel по умолчанию использует единый стиль для всего текста, но NSAttributedString решает эту задачу. Это мощный класс, позволяющий применять разные атрибуты (шрифт, цвет, межстрочный интервал, тени и т.д.) к отдельным фрагментам строки. Вот пошаговое решение вашей проблемы.
Базовый пример: жирный и обычный текст
Создадим атрибутивную строку, где слово «жирный» будет полужирным:
import UIKit
let label = UILabel()
let fullText = "Привет, мир! Это жирный текст"
let boldRange = (fullText as NSString).range(of: "жирный")
// Создаём атрибутивную строку с базовым шрифтом
let attributedString = NSMutableAttributedString(string: fullText)
// Устанавливаем жирный шрифт для нужного диапазона
let boldFont = UIFont.boldSystemFont(ofSize: 16)
attributedString.addAttribute(.font, value: boldFont, range: boldRange)
// Применяем к UILabel
label.attributedText = attributedString
Подробное объяснение ключевых моментов
- NSMutableAttributedString — изменяемая версия
NSAttributedString. Мы используем её, чтобы добавлять атрибуты поэтапно. - range(of:) — метод
NSString, который находит диапазон подстроки. Важно привести строку кNSString, так какNSRangeне совместим сRange<String.Index>напрямую. - addAttribute(_:value:range:) — добавляет один атрибут для указанного диапазона. В примере мы изменили только шрифт, но можно добавить и другие атрибуты (цвет, подчёркивание и т.д.).
Добавление нескольких атрибутов
Вы можете комбинировать атрибуты. Например, сделаем слово «жирный» жирным и красным, а слово «мир» — зелёным:
let attributedString = NSMutableAttributedString(string: "Привет, мир! Это жирный текст")
// Диапазоны
let worldRange = (attributedString.string as NSString).range(of: "мир")
let boldRange = (attributedString.string as NSString).range(of: "жирный")
// Атрибуты для "мир"
let worldAttributes: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.green,
.font: UIFont.italicSystemFont(ofSize: 16)
]
attributedString.addAttributes(worldAttributes, range: worldRange)
// Атрибуты для "жирный"
let boldAttributes: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.red,
.font: UIFont.boldSystemFont(ofSize: 16)
]
attributedString.addAttributes(boldAttributes, range: boldRange)
label.attributedText = attributedString
Работа с межстрочным интервалом и выравниванием
Атрибутивные строки также управляют параграфным стилем. Например, увеличим межстрочный интервал:
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 8 // 8 пикселей между строками
let attributedString = NSMutableAttributedString(string: "Привет, мир! Это жирный текст")
attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length))
label.attributedText = attributedString
Советы для начинающих
- Всегда проверяйте, что диапазон (range) корректен. Если подстрока не найдена,
range(of:)вернётNSRange(location: NSNotFound, length: 0), что приведёт к ошибке. Добавьте проверку:guard boldRange.location != NSNotFound else { return }. - Используйте
NSAttributedString.Keyдля доступа ко всем возможным атрибутам (шрифт, цвет, тень, зачёркивание и т.д.). Полный список — в документации Apple. - Для сложных случаев (например, разные шрифты в одной строке) удобно использовать библиотеки вроде SwiftRichString, но для базовых задач хватает стандартного API.
Теперь ваш UILabel сможет отображать текст с разными стилями. Удачи в разработке!
<<Альтернативный подход: использование расширения (extension) для удобства
Если вам часто приходится создавать атрибутивные строки, можно написать небольшое расширение для String, чтобы упростить код. Вот пример:
extension String {
func attributed(_ attributes: [NSAttributedString.Key: Any], for substring: String) -> NSAttributedString {
let attributedString = NSMutableAttributedString(string: self)
let range = (self as NSString).range(of: substring)
if range.location != NSNotFound {
attributedString.addAttributes(attributes, range: range)
}
return attributedString
}
}
// Использование:
let text = "Привет, мир! Это жирный текст"
let boldAttrs: [NSAttributedString.Key: Any] = [.font: UIFont.boldSystemFont(ofSize: 16), .foregroundColor: UIColor.red]
let attributedText = text.attributed(boldAttrs, for: "жирный")
label.attributedText = attributedText
Дополнительный совет: использование HTML
Если вы привыкли к HTML-разметке, можно преобразовать HTML-строку в атрибутивную. Это удобно для сложных форматирований (списки, ссылки), но работает медленнее и требует осторожности:
let htmlString = "Привет, мир! Это <b>жирный</b> текст"
if let data = htmlString.data(using: .utf8),
let attributedString = try? NSAttributedString(data: data,
options: [.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil) {
label.attributedText = attributedString
}
Этот метод подходит для динамического контента из сети, но для статического текста предпочтительнее первый способ — он производительнее и безопаснее.