NSTextAttachment: co to je a jak přidat obrázek do textu v iOS

Autor: IT Sectr Publikováno: 2026-07-25 Doba čtení: 9 min

NSTextAttachment je třída z frameworku UIKit, která umožňuje vkládání obrázků a dalších mediálních objektů do formátovaného textu prostřednictvím NSAttributedString. Pracuje na úrovni TextKit a Core Text, což vývojářům poskytuje kontrolu nad velikostí, pozicí a chováním příloh v textovém toku. Podle Apple Documentation (2025) NSTextAttachment podporuje obrázky, PDF a vlastní kontejnery zobrazení a integruje se s UITextView a UILabel. Porozumění tomuto API je nezbytné pro vytváření Rich Text v iOS aplikacích, od chatů a editorů po zpravodajské kanály s ikonami v popiscích.

Hlavní body

  • NSTextAttachment — třída UIKit pro vkládání médií do formátovaného iOS textu.
  • Obrázek se přidává přes NSAttributedString s klíčem NSAttachmentAttributeName.
  • Vlastnost bounds řídí velikost a vertikální posun přílohy.
  • NSTextAttachment podporuje obrázky, PDF a vlastní soubory přes datový kontejner.
  • API se integruje s UITextView, UILabel a TextKit pro flexibilní rozvržení textu.

Co je NSTextAttachment?

NSTextAttachment je třída z frameworku UIKit, která umožňuje vkládání mediálních objektů přímo do textového obsahu NSAttributedString. Na rozdíl od samostatného UIImageView umístěného vedle textu, NSTextAttachment činí obrázek součástí textového toku: obrázek se pohybuje spolu s řádky, účastní se zarovnání a zabírá místo jako běžný znak.

Třída je součástí architektury TextKit, která spravuje vykreslování textu v iOS a macOS. TextKit rozděluje text na glyfy, zohledňuje kerning, ligatury a řádkování, a NSTextAttachment se do tohoto potrubí zapojuje jako speciální znak, který se vykresluje nikoli jako písmeno, ale jako grafický objekt.

Každá instance NSTextAttachment obsahuje vlastnosti contents (data souboru), fileType (typ UTI obsahu) a bounds (obdélník v bodech určující velikost a polohu). Podle Apple Human Interface Guidelines je bounds ve výchozím nastavení roven velikosti obrázku, ale může být změněn pro přesné přizpůsobení písmu.

Použijte NSTextAttachment místo samostatného UIImageView, když se má obrázek chovat jako součást textu, v chatech, zpravodajských kanálech, textových editorech a formulářích s ikonami ve vstupních polích.

Jak přidat obrázek do textu přes NSTextAttachment

Základní scénář práce s NSTextAttachment se skládá ze tří kroků: vytvoření instance, nastavení obrázku a připojení k NSAttributedString. Podívejme se na proces na příkladu Swift.

swift
let attachment = NSTextAttachment()
attachment.image = UIImage(named: "icon-star")

let attachmentString = NSAttributedString(attachment: attachment)

let text = NSMutableAttributedString(string: "Rating: ")
text.append(attachmentString)

let label = UILabel()
label.attributedText = text

Po zavolání NSAttributedString(attachment:) se objekt NSTextAttachment převede na atribut NSAttachmentAttributeName, který se připojí ke speciálnímu náhradnímu znaku (object replacement character, kód 0xFFFC). Tento znak se nezobrazuje jako písmeno, místo něj se kreslí obrázek z vlastnosti image.

Pokud má být obrázek uprostřed řádku textu (například ikona za slovem), jednoduše vložte attachmentString na požadovanou pozici v NSMutableAttributedString. TextKit automaticky zohlední výšku řádku a zarovná obrázek na základní linii.

Důležité: vlastnost image je dostupná pouze v iOS (od iOS 7). V macOS použijte vlastnost contents s NSImage. Z důvodu zpětné kompatibility vždy nastavujte image přímo, nespoléhejte na datový kontejner.

Nastavení bounds a pozice přílohy

Ve výchozím nastavení NSTextAttachment zobrazuje obrázek v jeho původní velikosti v bodech. V praxi je téměř vždy nutné upravit velikost a vertikální polohu, k tomu slouží vlastnost bounds.

Struktura CGRect bounds zahrnuje origin (posun v X a Y) a size (šířka a výška). Posun v Y je obzvláště důležitý: záporná hodnota posouvá obrázek pod základní linii, kladná hodnota jej zvedá. Typický scénář je zarovnání ikony na střed řádku textu.

swift
let attachment = NSTextAttachment()
attachment.image = UIImage(named: "icon-star")

let font = UIFont.systemFont(ofSize: 16)
let fontCapHeight = font.capHeight
let imageSize = CGSize(width: 18, height: 18)

attachment.bounds = CGRect(
    x: 0,
    y: (fontCapHeight - imageSize.height) / 2,
    width: imageSize.width,
    height: imageSize.height
)

Výpočet zarovnání používá capHeight písma, výšku velkého písmena, nikoli plnou výšku řádku. To zaručuje, že ikona vizuálně odpovídá horní hranici textu a nevisí mezi baseline a ascender. Velikost obrázku v příkladu je 18×18 pt, což je typické pro ikony v UI textu.

Pokud má být obrázek větší než řádek textu (například náhled fotografie v chatu), TextKit automaticky zvětší řádkování pro aktuální řádek. V tomto případě se bounds nastaví na přirozenou velikost a posun v Y je nulový.

PDF a vlastní přílohy

NSTextAttachment podporuje nejen PNG a JPEG, ale také dokumenty PDF a libovolné soubory prostřednictvím vlastnosti contents. To z něj činí univerzální nástroj pro Rich Text v iOS aplikacích.

Při nastavení PDF obrázku v attachment.image systém automaticky vykreslí první stránku dokumentu. Pro přesné zobrazení však použijte data přímo přes inicializátor s data a typem UTI:

swift
guard let pdfData = Bundle.main.url(forResource: "document",
                                  withExtension: "pdf") else { return }

let fileData = Data(contentsOf: pdfData)
let attachment = NSTextAttachment(data: fileData,
                                       ofType: "com.adobe.pdf")

attachment.bounds = CGRect(x: 0, y: -4,
                           width: 24, height: 24)

let pdfString = NSAttributedString(attachment: attachment)

Parametr ofType přijímá řetězec UTI (Uniform Type Identifier). Standardní typy: public.image (jakýkoli obrázek), public.jpeg, public.png, com.adobe.pdf. Při zadání správného UTI systém zvolí odpovídající metodu vykreslení, pro PDF je to CGPDFDocument, pro obrázky CGImageSource.

Pro vlastní typy souborů (např. vektorová grafika ve formátu SVG) bude potřeba podtřída NSTextAttachment přepisující metodu image(forBounds:textContainer:characterIndex:). Pokud standardní vykreslení nevyhovuje, vraťte nil a implementujte kreslení přes Core Graphics v metodě draw.

NSTextAttachment v UITextView a delegace

NSTextAttachment funguje správně jak v UILabel, tak v UITextView. UITextView však poskytuje více možností: interakci s přílohami (klepnutí na ikonu), editaci textu spolu s obrázky a podporu NSAttachmentBehavior.

Pro zpracování klepnutí na NSTextAttachment v UITextView se používá delegát UITextViewDelegate a metoda textView(_:shouldInteractWith:in:interaction:). Tato metoda je volána, když uživatel klepne na přílohu, a umožňuje přejít na obrazovku, otevřít popup nebo přehrát animaci.

swift
func textView(_ textView: UITextView,
                shouldInteractWith attachment: NSTextAttachment,
                in characterRange: NSRange,
                interaction: UITextItemInteraction) -> Bool {
    if interaction == .preview {
        return false
    }
    // Otevřít obrazovku detailů
    showImageDetail(attachment.image)
    return false
}

Metoda rozlišuje typy interakce pomocí parametru interaction: .preview (3D Touch / Haptic Touch), .default (běžné klepnutí) a .presentActions (kontextové menu). Pro každý typ můžete nastavit vlastní chování nebo jej zakázat vrácením false.

Při editaci UITextView s NSTextAttachment je důležité pamatovat: odstranění náhradního znaku (0xFFFC) odstraní i přílohu. Uživatel vidí obrázek jako jeden celek, vybírá se celý, nikoli pixel po pixelu. Pro podporu přetahování příloh v iOS 15+ použijte NSTextAttachmentViewProvider.

Typické chyby při práci s NSTextAttachment

První častá chyba — ignorování bounds. Vývojáři se často spoléhají na původní velikost obrázku, což vede k obřím ikonám v textu nebo naopak k obrázkům, které jsou sotva viditelné. Vždy nastavujte bounds explicitně s ohledem na písmo a kontext.

Druhá chyba — nesprávný posun v Y. Kladná hodnota v bounds.origin.y posouvá obrázek dolů (v souřadnicovém systému UIKit osa Y směřuje dolů, což se zdá nelogické, ale tak Core Graphics funguje). Pro zarovnání na střed řádku použijte vzorec s capHeight písma, jak je uvedeno v sekci 3.

Třetí problém — ztráta obrázku při změně traitCollection. Když uživatel přepne Dark Mode nebo Dynamic Type, velikost písma se může změnit, ale bounds zůstává stejný. Řešení — vypočítávat bounds dynamicky v metodě layoutSubviews nebo pomocí KVO na font.

Čtvrtá častá chyba — použití NSTextAttachment v UILabel s numberOfLines > 1. Ve víceřádkovém režimu a omezené šířce TextKit správně přenáší řádky spolu s obrázkem. Problém nastává, když výška přílohy přesahuje výšku řádku, sousední řádky se překrývají. Řešení — zvýšit lineSpacing pomocí NSMutableParagraphStyle.

Často kladené otázky

Čím se liší NSTextAttachment od UIImageView v textu?

NSTextAttachment činí obrázek součástí textového toku: pohybuje se, zarovnává a škáluje spolu s textem. UIImageView je vázán na souřadnice superview a neúčastní se rozvržení textu.

Lze přidat NSTextAttachment do UILabel?

Ano, pokud nastavíte vlastnost attributedText místo text. UILabel správně zobrazuje NSTextAttachment, ale nepodporuje interaktivitu. Pro klepnutí na přílohu použijte UITextView.

Jak změnit velikost obrázku po vytvoření attachmentu?

Změňte vlastnost bounds existující instance NSTextAttachment. Text se automaticky přerenderuje s novými rozměry bez nutnosti vytvářet nový NSAttributedString.

Podporuje NSTextAttachment animované obrázky?

NSTextAttachment podporuje statické obrázky. Pro GIF a animované formáty je vyžadována vlastní implementace přes NSTextAttachmentViewProvider v iOS 15+ nebo přes CADisplayLink.

Jak přidat NSTextAttachment do textu programově?

Vytvořte instanci NSTextAttachment, nastavte image nebo data, určete bounds, zabalte do NSAttributedString(attachment:) a vložte do NSMutableAttributedString metodou insert(_:at:).

Shrnutí

  • NSTextAttachment — třída UIKit pro vkládání obrázků, PDF a dalších médií do formátovaného textu.
  • Obrázek se přidává přes NSAttributedString(attachment:) a stává se součástí textového toku.
  • Vlastnost bounds řídí velikost a pozici: vždy ji nastavujte explicitně s ohledem na písmo.
  • Pro zarovnání ikony na střed řádku použijte vzorec s capHeight aktuálního písma.
  • PDF přílohy jsou podporovány přes inicializátor s data a správným typem UTI.
  • Pro zpracování klepnutí na přílohu použijte UITextViewDelegate a metodu shouldInteractWith.
  • Při změně Dynamic Type přepočítávejte bounds dynamicky, abyste předešli překrývání řádků.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také