NSAttributedString — co to jest, formatowanie tekstu i atrybuty w iOS

Autor: IT Sectr Opublikowano: 2026-07-23 Czas czytania: 9 min

NSAttributedString — to klasa z frameworku Foundation w iOS SDK, reprezentująca ciąg znaków z zestawem atrybutów formatowania stosowanych do pojedynczych znaków lub zakresów tekstu. W przeciwieństwie do zwykłego NSString, NSAttributedString przechowuje nie tylko znaki Unicode, ale także słownik atrybutów (czcionka, kolor, odstęp między znakami, wyrównanie) dla każdego segmentu ciągu. Według Apple Developer Documentation (2026), NSAttributedString stanowi podstawę do wyświetlania sformatowanego tekstu we wszystkich komponentach UI w iOS.

Najważniejsze

  • NSAttributedString — niezmienny ciąg z atrybutami, gdzie każdemu znakowi lub zakresowi odpowiada słownik atrybutów NSAttributedStringKey
  • NSMutableAttributedString — zmienna wersja z metodami addAttribute, setAttributes, replaceCharacters do modyfikacji atrybutów w runtime
  • Podstawowe atrybuty: .font, .foregroundColor, .paragraphStyle, .kern, .underlineStyle, .strikethroughStyle, .link, .backgroundColor
  • NSMutableParagraphStyle — obiekt pomocniczy do ustawiania wyrównania, odstępu między wierszami, wcięć i kierunku tekstu
  • UILabel, UITextView, UITextField obsługują attributedText do wyświetlania atrybutowanych ciągów

Co to jest NSAttributedString?

NSAttributedString — to fundamentalna klasa iOS/macOS do pracy z sformatowanym tekstem. Rozszerza możliwości NSString, dodając do ciągu atrybuty — słownik par klucz-wartość, gdzie klucz to stała NSAttributedStringKey (np. .font, .foregroundColor), a wartość to odpowiedni obiekt (UIFont, UIColor). Każdy znak w ciągu może mieć własny zestaw atrybutów, co pozwala zrealizować mieszane formatowanie w jednym ciągu.

Architektura NSAttributedString opiera się na koncepcji zakresów atrybutów (attribute runs). Jeśli ustawisz atrybut .font = UIFont.boldSystemFont(ofSize: 16) dla zakresu znaków 0..5, wszystkie znaki tego zakresu wyświetlą się pogrubioną czcionką. Pozostałe znaki mogą mieć inną czcionkę lub nie mieć atrybutu wcale. Podczas wyświetlania atrybutowanego ciągu system UIKit łączy cechy z różnych zakresów i renderuje tekst jednolicie.

NSAttributedString jest niezmienny — po utworzeniu jego atrybuty i zawartość nie mogą być zmienione. Do modyfikacji istnieje podklasa NSMutableAttributedString, która udostępnia metody dodawania, usuwania i zmiany atrybutów w dowolnych zakresach. Ta różnica jest istotna dla wielowątkowości: niezmienny NSAttributedString jest bezpieczny wątkowo, a NSMutableAttributedString — nie.

Podstawowe atrybuty formatowania tekstu

NSAttributedString obsługuje około 40 standardowych atrybutów zdefiniowanych w NSAttributedStringKey. Każdy atrybut wpływa na określony aspekt wyglądu tekstu: czcionkę, kolor, położenie, podkreślenie, cień, odstęp między znakami, styl akapitu i hiperłącza. Do ustawienia atrybutu używa się stałej NSAttributedStringKey, której przypisuje się obiekt odpowiedniego typu.

Klucz atrybutuTyp wartościPrzeznaczenie
.fontUIFontCzcionka i rozmiar tekstu
.foregroundColorUIColorKolor tekstu
.backgroundColorUIColorKolor tła pod tekstem
.paragraphStyleNSParagraphStyleWyrównanie, odstęp między wierszami, wcięcia
.kernNSNumber (Float)Odstęp między znakami (kerning)
.underlineStyleNSUnderlineStyle (Int)Styl podkreślenia (single, double, thick, pattern)
.strikethroughStyleNSUnderlineStyle (Int)Styl przekreślenia
.linkNSURLURL dla interaktywnego hiperłącza
.shadowNSShadowCień tekstu z offset, blurRadius i kolorem
.baselineOffsetNSNumber (Float)Przesunięcie tekstu względem linii bazowej

NSParagraphStyle — formatowanie akapitu

NSMutableParagraphStyle — obiekt zarządzający wizualnymi cechami akapitu: wyrównanie (.alignment: .left, .center, .right, .justified), odstęp między wierszami (.lineSpacing), odstęp między akapitami (.paragraphSpacing), wcięcie pierwszego wiersza (.firstLineHeadIndent), wcięcie lewe i prawe (.headIndent, .tailIndent) oraz kierunek tekstu (.baseWritingDirection). ParagraphStyle stosuje się do zakresu, który obejmuje znaki nowej linii, jeśli wymagane jest jednakowe formatowanie dla całego akapitu.

Jak utworzyć NSAttributedString w kodzie

Tworzenie NSAttributedString odbywa się przez inicjalizator przyjmujący ciąg i słownik atrybutów. Atrybuty są stosowane do całego ciągu. Do mieszanego formatowania (różne atrybuty w różnych częściach ciągu) używa się NSMutableAttributedString z następnym dodawaniem atrybutów do konkretnych zakresów. Objective-C używa słownika NSAttributedStringKey: UIFont, a Swift — typowo bezpiecznego słownika [NSAttributedString.Key: Any].

swift
let plainText = "Hello, Swift!"

// Create with uniform attributes for the entire string
let attributes: [NSAttributedString.Key: Any] = [
    NSAttributedString.Key.font:
        UIFont.systemFont(ofSize: 18),
    NSAttributedString.Key.foregroundColor:
        UIColor.darkText,
    NSAttributedString.Key.kern: 1.5
]

let attributedString =
    NSAttributedString(string: plainText,
                        attributes: attributes)

Tworzenie z NSMutableParagraphStyle

Przykład demonstruje formatowanie akapitu przez NSMutableParagraphStyle. Ustawiane jest wyrównanie do środka, odstęp między wierszami 8 punktów, odstęp po akapicie 12 punktów. ParagraphStyle jest dodawany do słownika atrybutów pod kluczem .paragraphStyle. NSAttributedString kopiuje przekazany paragraphStyle, więc po utworzeniu ciągu można go zmieniać bez wpływu na już utworzony ciąg.

swift
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.center
paragraphStyle.lineSpacing = 8.0
paragraphStyle.paragraphSpacing = 12.0
paragraphStyle.firstLineHeadIndent = 20.0

let attributed = NSAttributedString(
    string: "Centered paragraph with spacing",
    attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle])

NSMutableAttributedString i zmiana atrybutów

NSMutableAttributedString — to podklasa NSAttributedString, która umożliwia zmianę zawartości i atrybutów po utworzeniu. Główne metody: addAttribute(_:value:range:) do dodania jednego atrybutu do zakresu; addAttributes(_:range:) do dodania wielu atrybutów; setAttributes(_:range:) do zastąpienia wszystkich atrybutów w zakresie; removeAttribute(_:range:) do usunięcia atrybutu; replaceCharacters(in:with:) do zastąpienia tekstu.

addAttribute i addAttributes dodają atrybuty do istniejących, nie usuwając już ustawionych. Jeśli w zakresie istnieje już atrybut z tym samym kluczem, jego wartość jest zastępowana. setAttributes całkowicie zastępuje słownik atrybutów dla zakresu — wszystkie wcześniej ustawione atrybuty są usuwane. To ważne przy sekwencyjnym formatowaniu jednego ciągu: addAttributes jest bezpieczniejszy, ponieważ nie resetuje już ustawionych czcionek i kolorów.

Zakresy (NSRange) są określane strukturą NSRange(location: 0, length: 5). location — indeks początkowy (0-bazowany), length — liczba znaków. Jeśli zakres wychodzi poza granice ciągu, NSMutableAttributedString generuje wyjątek NSRangeException. Do bezpiecznej pracy z zakresami używa się metod NSRange z Foundation, takich jak NSIntersectionRange i NSUnionRange.

swift
let attributed = NSMutableAttributedString(
    string: "Bold and red text here")

// Apply bold font to first 9 characters
let boldRange = NSRange(location: 0, length: 9)
attributed.addAttribute(
    NSAttributedString.Key.font,
    value: UIFont.boldSystemFont(ofSize: 16),
    range: boldRange)

// Apply red color to characters 13-16 ("text")
let redRange = NSRange(location: 13, length: 4)
attributed.addAttribute(
    NSAttributedString.Key.foregroundColor,
    value: UIColor.red,
    range: redRange)

// Apply underline to the entire string
let fullRange = NSRange(location: 0,
                       length: attributed.length)
attributed.addAttribute(
    NSAttributedString.Key.underlineStyle,
    value: NSUnderlineStyle.single.rawValue,
    range: fullRange)

Przykład wyświetlania atrybutowanego ciągu w UILabel

Najbardziej powszechny sposób wyświetlania NSAttributedString — przypisanie go do właściwości attributedText UILabel. W przeciwieństwie do właściwości text, attributedText używa atrybutów do renderowania, obsługując mieszane formatowanie. Ważne: jeśli ustawiono attributedText, UILabel ignoruje właściwości font, textColor, textAlignment — wszystkie cechy wizualne pochodzą z atrybutów NSAttributedString.

swift
let label = UILabel()
label.numberOfLines = 0

let fullText = NSMutableAttributedString(
    string: "Price: $24.99 per month")

// Format "Price:" label with bold font
let priceLabelRange = NSRange(
    location: 0, length: 6)
fullText.addAttribute(
    NSAttributedString.Key.font,
    value: UIFont.boldSystemFont(ofSize: 16),
    range: priceLabelRange)

// Format "$24.99" with green color
let amountRange = NSRange(
    location: 7, length: 6)
fullText.addAttribute(
    NSAttributedString.Key.foregroundColor,
    value: UIColor.systemGreen(),
    range: amountRange)
fullText.addAttribute(
    NSAttributedString.Key.font,
    value: UIFont.boldSystemFont(ofSize: 22),
    range: amountRange)

// Apply gray color to "per month" text
let periodRange = NSRange(
    location: 14, length: 9)
fullText.addAttribute(
    NSAttributedString.Key.foregroundColor,
    value: UIColor.secondaryLabel,
    range: periodRange)

label.attributedText = fullText

Wyświetlanie w UITextView z interaktywnymi linkami

UITextView obsługuje interaktywne linki w NSAttributedString. Atrybut .link z NSURL sprawia, że tekst jest klikalny. Do obsługi kliknięć używa się delegata UITextViewDelegate z metodą textView(_:shouldInteractWith:in:interaction:). UITextView obsługuje również zaznaczanie tekstu i korzystanie z UIMenuController dla standardowych operacji (kopiowanie, wyszukiwanie).

Konwersja NSAttributedString do HTML i RTF

NSAttributedString obsługuje konwersję z HTML i RTF przez NSAttributedString.DocumentType. Do załadowania HTML używa się inicjalizatora z parametrami documentAttributes: NSAttributedString(data: htmlData, options: [.documentType: .html], documentAttributes: nil). Analogicznie dla RTF: .rtf lub .rtfd. Ten mechanizm jest przydatny do wyświetlania treści HTML bez WebView.

Do eksportu do HTML używa się metody data(from:documentAttributes:) z zakresem i typem dokumentu. Export HTML: try attributedString.data(from: fullRange, documentAttributes: [.documentType: .html]). Otrzymane dane można zapisać do pliku, wysłać na serwer lub wyświetlić w WebView. Podczas eksportu zachowywane są czcionki, kolory, wyrównanie, listy — wszystkie atrybuty formatowania są konwertowane do stylów CSS.

Wsparcie dla RTF jest szczególnie istotne w aplikacjach macOS, gdzie RTF jest standardowym formatem tekstu sformatowanego. iOS również obsługuje odczyt i zapis RTF, ale nie używa go jako podstawowego formatu. Różnica między RTF a RTFD: RTFD zawiera zagnieżdżone zasoby (obrazy) spakowane w katalog. NSAttributedString może obsługiwać oba formaty przez jednolity interfejs.

swift
let htmlString = "<p><b>Bold<\/b> and <i>italic<\/i><\/p>"
guard let htmlData = htmlString.data(
    using: String.Encoding.utf8) else { return }

let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
    NSAttributedString.DocumentReadingOptionKey.documentType:
        NSAttributedString.DocumentType.html
]

let attributedFromHTML =
    try? NSAttributedString(
        data: htmlData,
        options: options,
        documentAttributes: nil)

Często zadawane pytania

Jaka jest różnica między NSString a NSAttributedString?

NSString przechowuje tylko sekwencję znaków Unicode bez żadnych informacji o formatowaniu. NSAttributedString przechowuje znaki i dla każdego podzakresu zawiera słownik atrybutów (czcionka, kolor, styl). Podczas wyświetlania NSAttributedString UIKit używa tych atrybutów do renderowania, tworząc sformatowany tekst.

Dlaczego UILabel nie wyświetla atrybutów NSAttributedString?

Najczęstszą przyczyną jest użycie właściwości text zamiast attributedText. Przy przypisaniu przez text wszystkie atrybuty są ignorowane. Drugą przyczyną: po ustawieniu attributedText zmieniasz font, textColor lub textAlignment UILabel — te zmiany resetują attributedText. Używaj tylko attributedText dla sformatowanego tekstu.

Jak zastosować różne czcionki w jednym ciągu?

Utwórz NSMutableAttributedString i wywołaj addAttribute(.font, value: boldFont, range: boldRange) dla każdego fragmentu z inną czcionką. Każde wywołanie stosuje atrybut tylko do określonego zakresu. Pozostałe znaki zachowują standardową czcionkę lub inną ustawioną wcześniej. W ten sposób tworzone są zakresy atrybutów (attribute runs) z różnymi czcionkami.

Czy NSAttributedString działa z tekstem wieloliniowym?

Tak, NSAttributedString poprawnie obsługuje tekst wieloliniowy, w tym znaki nowej linii ( ). UITextView i UILabel (z numberOfLines = 0) automatycznie przenoszą tekst do nowej linii. NSMutableParagraphStyle zarządza odstępem między wierszami, wcięciami i wyrównaniem dla każdego akapitu niezależnie.

Jak utworzyć kolorowy tekst z różnymi kolorami w jednym ciągu?

Użyj NSMutableAttributedString z atrybutem .foregroundColor dla każdego zakresu kolorów. Dla czerwonego tekstu: addAttribute(.foregroundColor, value: UIColor.red, range: firstRange). Dla niebieskiego: addAttribute(.foregroundColor, value: UIColor.blue, range: secondRange). Kolory zostaną zastosowane tylko do określonych zakresów znaków.

Podsumowanie

  • NSAttributedString — ciąg z atrybutami formatowania (czcionka, kolor, styl), przechowywanymi w słowniku dla każdego zakresu znaków
  • NSMutableAttributedString — zmienna wersja z metodami addAttribute, setAttributes i removeAttribute do dynamicznego formatowania
  • Podstawowe atrybuty: .font, .foregroundColor, .paragraphStyle, .kern, .underlineStyle, .strikethroughStyle, .link, .shadow, .baselineOffset
  • NSMutableParagraphStyle zarządza wyrównaniem, odstępem między wierszami, wcięciami i kierunkiem tekstu dla akapitów
  • UILabel, UITextView, UITextField obsługują wyświetlanie sformatowanego tekstu przez właściwość attributedText
  • Konwersja HTML/RTF — NSAttributedString obsługuje import i eksport sformatowanego tekstu przez documentType

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również