NSTextAttachment: vad är det och hur man lägger till en bild i text på iOS

Författare: IT Sectr Publicerad: 2026-07-25 Lästid: 9 min

NSTextAttachment är en klass från UIKit-ramverket som gör det möjligt att bädda in bilder och andra mediaobjekt i formaterad text via NSAttributedString. Den fungerar på TextKit- och Core Text-nivå och ger utvecklare kontroll över storlek, position och beteende för bilagor i textflödet. Enligt Apple Documentation (2025) stöder NSTextAttachment bilder, PDF och anpassade vycontainrar och integreras med UITextView och UILabel. Förståelse för detta API är nödvändigt för att skapa Rich Text i iOS-appar, från chattar och redigerare till nyhetsflöden med ikoner i bildtexter.

Huvudpunkter

  • NSTextAttachment — UIKit-klass för att bädda in media i formaterad iOS-text.
  • Bild läggs till via NSAttributedString med nyckeln NSAttachmentAttributeName.
  • Egenskapen bounds styr storlek och vertikal förskjutning av bilagan.
  • NSTextAttachment stöder bilder, PDF och anpassade filer via databehållare.
  • API integreras med UITextView, UILabel och TextKit för flexibel textlayout.

Vad är NSTextAttachment?

NSTextAttachment är en klass från UIKit-ramverket som gör det möjligt att bädda in mediaobjekt direkt i textinnehållet i NSAttributedString. Till skillnad från en separat UIImageView placerad bredvid texten, gör NSTextAttachment bilden till en del av textflödet: bilden flyttas med raderna, deltar i justering och tar plats som ett vanligt tecken.

Klassen är en del av TextKit-arkitekturen som hanterar textrendering på iOS och macOS. TextKit delar upp text i glyfer, tar hänsyn till kerning, ligaturer och radavstånd, och NSTextAttachment ansluter till denna pipeline som ett specialtecken som renderas inte som en bokstav utan som ett grafiskt objekt.

Varje NSTextAttachment-instans innehåller egenskaperna contents (fildata), fileType (UTI-typ av innehåll) och bounds (rektangel i punkter som definierar storlek och position). Enligt Apple Human Interface Guidelines är bounds som standard lika med bildens storlek men kan ändras för exakt passform till teckensnittet.

Använd NSTextAttachment istället för en separat UIImageView när bilden ska bete sig som en del av texten, i chattar, nyhetsflöden, textredigerare och formulär med ikoner i inmatningsfält.

Hur man lägger till en bild i text via NSTextAttachment

Grundscenariot för arbete med NSTextAttachment består av tre steg: skapa en instans, ställa in bilden och bifoga till NSAttributedString. Låt oss titta på processen med ett Swift-exempel.

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

Efter anrop av NSAttributedString(attachment:) omvandlas NSTextAttachment-objektet till attributet NSAttachmentAttributeName som bifogas till ett speciellt ersättningstecken (object replacement character, kod 0xFFFC). Detta tecken visas inte som en bokstav, istället ritas bilden från egenskapen image.

Om bilden ska vara i mitten av en textrad (till exempel en ikon efter ett ord), sätt helt enkelt in attachmentString på önskad position i NSMutableAttributedString. TextKit tar automatiskt hänsyn till radhöjden och justerar bilden mot baslinjen.

Viktigt: egenskapen image är endast tillgänglig på iOS (från och med iOS 7). På macOS använder du egenskapen contents med NSImage. För bakåtkompatibilitet, ställ alltid in image direkt, lita inte på databehållaren.

Konfiguration av bounds och bilageposition

Som standard visar NSTextAttachment bilden i sin ursprungliga storlek i punkter. I praktiken krävs nästan alltid justering av storlek och vertikal position, för detta används egenskapen bounds.

Strukturen CGRect bounds innehåller origin (förskjutning i X och Y) och size (bredd och höjd). Förskjutning i Y är särskilt viktig: ett negativt värde sänker bilden under baslinjen, ett positivt värde höjer den. Ett typiskt scenario är att centrera en ikon i en textrad.

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
)

Beräkning av justering använder teckensnittets capHeight, höjden på en versal, inte hela radhöjden. Detta garanterar att ikonen visuellt matchar textens övre kant och inte svänger mellan baseline och ascender. Bildstorleken i exemplet är 18×18 pt, vilket är typiskt för ikoner i UI-text.

Om bilden måste vara större än textraden (till exempel en fotoförhandsvisning i en chatt), ökar TextKit automatiskt radavståndet för den aktuella raden. I detta fall ställs bounds in på naturlig storlek och förskjutningen i Y är noll.

PDF och anpassade bilagor

NSTextAttachment stöder inte bara PNG och JPEG, utan även PDF-dokument och godtyckliga filer via egenskapen contents. Detta gör det till ett universellt verktyg för Rich Text i iOS-appar.

När du ställer in en PDF-bild i attachment.image renderar systemet automatiskt dokumentets första sida. För exakt visning, använd dock data direkt via initieraren med data och UTI-typ:

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)

Parametern ofType accepterar en UTI-sträng (Uniform Type Identifier). Standardtyper: public.image (vilken bild som helst), public.jpeg, public.png, com.adobe.pdf. Vid angivelse av korrekt UTI väljer systemet lämplig renderingsmetod, för PDF är det CGPDFDocument, för bilder CGImageSource.

För anpassade filtyper (till exempel vektorgrafik i SVG-format) krävs en underklass av NSTextAttachment som åsidosätter metoden image(forBounds:textContainer:characterIndex:). Om standardrendering inte är lämplig, returnera nil och implementera ritning via Core Graphics i metoden draw.

NSTextAttachment i UITextView och delegering

NSTextAttachment fungerar korrekt både i UILabel och i UITextView. UITextView ger dock fler möjligheter: interaktion med bilagor (tryck på ikon), redigering av text tillsammans med bilder och stöd för NSAttachmentBehavior.

För att hantera tryck på NSTextAttachment i UITextView används delegaten UITextViewDelegate och metoden textView(_:shouldInteractWith:in:interaction:). Denna metod anropas när användaren trycker på bilagan och möjliggör navigering till en skärm, öppning av popup eller uppspelning av animation.

swift
func textView(_ textView: UITextView,
                shouldInteractWith attachment: NSTextAttachment,
                in characterRange: NSRange,
                interaction: UITextItemInteraction) -> Bool {
    if interaction == .preview {
        return false
    }
    // Öppna detaljskärm
    showImageDetail(attachment.image)
    return false
}

Metoden särskiljer interaktionstyper via parametern interaction: .preview (3D Touch / Haptic Touch), .default (vanligt tryck) och .presentActions (kontextmeny). För varje typ kan du ställa in eget beteende eller förbjuda det genom att returnera false.

Vid redigering av UITextView med NSTextAttachment är det viktigt att komma ihåg: borttagning av ersättningstecknet (0xFFFC) tar också bort bilagan. Användaren ser bilden som ett enda element, den väljs i sin helhet, inte pixel för pixel. För stöd av dragning av bilagor i iOS 15+, använd NSTextAttachmentViewProvider.

Vanliga misstag vid arbete med NSTextAttachment

Det första vanliga misstaget — att ignorera bounds. Utvecklare förlitar sig ofta på bildens ursprungliga storlek, vilket leder till gigantiska ikoner i texten eller omvänt till bilder som knappt syns. Ställ alltid in bounds explicit med hänsyn till teckensnitt och sammanhang.

Det andra misstaget — felaktig Y-förskjutning. Ett positivt värde i bounds.origin.y sänker bilden (i UIKit-koordinatsystemet pekar Y-axeln nedåt, detta verkar ologiskt men så fungerar Core Graphics). För justering till mitten av raden, använd formeln med teckensnittets capHeight som visas i avsnitt 3.

Det tredje problemet — förlust av bild vid ändring av traitCollection. När användaren växlar mellan Dark Mode eller Dynamic Type kan teckensnittsstorleken ändras medan bounds förblir densamma. Lösning — beräkna bounds dynamiskt i metoden layoutSubviews eller via KVO på font.

Det fjärde vanliga misstaget — användning av NSTextAttachment i UILabel med numberOfLines > 1. I flerradigt läge och begränsad bredd överför TextKit korrekt rader tillsammans med bilden. Problemet uppstår när bilagans höjd överstiger radhöjden, angränsande rader överlappar varandra. Lösning — öka lineSpacing via NSMutableParagraphStyle.

Vanliga frågor

Vad är skillnaden mellan NSTextAttachment och UIImageView i text?

NSTextAttachment gör bilden till en del av textflödet: den flyttas, justeras och skalas med texten. UIImageView är bunden till superview-koordinater och deltar inte i textlayout.

Kan NSTextAttachment läggas till i UILabel?

Ja, om du ställer in egenskapen attributedText istället för text. UILabel visar NSTextAttachment korrekt men stöder inte interaktivitet. För tryck på bilagan, använd UITextView.

Hur ändrar man bildstorleken efter att ha skapat en attachment?

Ändra egenskapen bounds för den befintliga NSTextAttachment-instansen. Texten renderas automatiskt om med de nya måtten utan att behöva skapa en ny NSAttributedString.

Stöder NSTextAttachment animerade bilder?

NSTextAttachment stöder statiska bilder. För GIF och animerade format krävs en anpassad implementering via NSTextAttachmentViewProvider i iOS 15+ eller via CADisplayLink.

Hur lägger man till NSTextAttachment i text programmatiskt?

Skapa en NSTextAttachment-instans, ställ in image eller data, ange bounds, slå in i NSAttributedString(attachment:) och sätt in i NSMutableAttributedString via metoden insert(_:at:).

Sammanfattning

  • NSTextAttachment — UIKit-klass för att bädda in bilder, PDF och annan media i formaterad text.
  • Bild läggs till via NSAttributedString(attachment:) och blir en del av textflödet.
  • Egenskapen bounds styr storlek och position: ställ alltid in den explicit med hänsyn till teckensnittet.
  • För att centrera en ikon i en rad, använd formeln med capHeight för aktuellt teckensnitt.
  • PDF-bilagor stöds via initierare med data och korrekt UTI-typ.
  • För att hantera tryck på bilaga, använd UITextViewDelegate och metoden shouldInteractWith.
  • Vid Dynamic Type-ändring, beräkna om bounds dynamiskt för att undvika överlappning av rader.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också