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 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.
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.
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.
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.
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ý.
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:
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 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.
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.
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
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.
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.
Změňte vlastnost bounds existující instance NSTextAttachment. Text se automaticky přerenderuje s novými rozměry bez nutnosti vytvářet nový NSAttributedString.
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.
Vytvořte instanci NSTextAttachment, nastavte image nebo data, určete bounds, zabalte do NSAttributedString(attachment:) a vložte do NSMutableAttributedString metodou insert(_:at:).
Shrnutí
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í.
Přečtěte si také