NSTextAttachment adalah kelas dari framework UIKit yang memungkinkan penyematan gambar dan objek media lainnya ke dalam teks terformat melalui NSAttributedString. Ini bekerja di tingkat TextKit dan Core Text, memberikan pengembang kendali atas ukuran, posisi, dan perilaku lampiran dalam aliran teks. Menurut Apple Documentation (2025), NSTextAttachment mendukung gambar, PDF, dan kontainer tampilan kustom, berintegrasi dengan UITextView dan UILabel. Memahami API ini sangat penting untuk membuat Rich Text di aplikasi iOS, mulai dari chat dan editor hingga feed berita dengan ikon di keterangan.
Poin Utama
NSTextAttachment adalah kelas dari framework UIKit yang memungkinkan penyematan objek media langsung ke dalam konten teks NSAttributedString. Tidak seperti UIImageView terpisah yang ditempatkan di samping teks, NSTextAttachment menjadikan gambar sebagai bagian dari aliran teks: gambar berpindah bersama baris, berpartisipasi dalam perataan, dan menempati ruang seperti karakter biasa.
Kelas ini adalah bagian dari arsitektur TextKit yang mengelola rendering teks di iOS dan macOS. TextKit memecah teks menjadi glyphs, mempertimbangkan kerning, ligatur, dan interline — dan NSTextAttachment bergabung ke dalam jalur ini sebagai karakter khusus yang dirender bukan sebagai huruf, melainkan sebagai objek grafis.
Setiap instance NSTextAttachment berisi properti contents (data file), fileType (tipe UTI konten), dan bounds (persegi panjang dalam points yang menentukan ukuran dan posisi). Menurut Apple Human Interface Guidelines, bounds secara default sama dengan ukuran gambar, tetapi dapat diubah untuk penyesuaian yang tepat dengan font.
Gunakan NSTextAttachment sebagai ganti UIImageView terpisah ketika gambar harus berperilaku sebagai bagian dari teks, di chat, feed berita, editor teks, dan formulir dengan ikon di kolom input.
Skenario dasar bekerja dengan NSTextAttachment terdiri dari tiga langkah: membuat instance, mengatur gambar, dan melampirkan ke NSAttributedString. Mari kita lihat prosesnya dengan contoh 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
Setelah memanggil NSAttributedString(attachment:), objek NSTextAttachment diubah menjadi atribut NSAttachmentAttributeName yang dilampirkan ke karakter pengganti khusus (object replacement character, kode 0xFFFC). Karakter ini tidak ditampilkan sebagai huruf — sebagai gantinya gambar dari properti image digambar.
Jika gambar harus ditempatkan di tengah baris teks (misalnya ikon setelah kata), cukup masukkan attachmentString ke posisi yang diinginkan di NSMutableAttributedString. TextKit secara otomatis memperhitungkan tinggi baris dan meratakan gambar pada garis dasar.
Penting: properti image hanya tersedia di iOS (mulai iOS 7). Di macOS gunakan properti contents dengan NSImage. Untuk kompatibilitas mundur, selalu atur image secara langsung, jangan bergantung pada kontainer data.
Secara default NSTextAttachment menampilkan gambar pada ukuran asli dalam points. Dalam praktiknya hampir selalu diperlukan penyesuaian ukuran dan posisi vertikal, untuk ini digunakan properti bounds.
Struktur CGRect bounds mencakup origin (pergeseran pada X dan Y) dan size (lebar dan tinggi). Pergeseran pada Y sangat penting: nilai negatif menurunkan gambar di bawah garis dasar, nilai positif menaikkannya. Skenario tipikal — meratakan ikon ke tengah baris teks.
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
)
Perhitungan perataan menggunakan capHeight font — tinggi huruf kapital, bukan tinggi baris penuh. Ini memastikan ikon secara visual cocok dengan batas atas teks, tidak melayang di antara baseline dan ascender. Ukuran gambar dalam contoh adalah 18×18 pt, tipikal untuk ikon dalam teks UI.
Jika gambar harus lebih besar dari baris teks (misalnya pratinjau foto di chat), TextKit secara otomatis meningkatkan spasi baris untuk baris saat ini. Dalam kasus ini, bounds diatur ke ukuran alami, dan pergeseran Y adalah nol.
NSTextAttachment mendukung tidak hanya PNG dan JPEG, tetapi juga dokumen PDF serta file arbitrer melalui properti contents. Ini menjadikannya alat universal untuk Rich Text di aplikasi iOS.
Saat mengatur gambar PDF di attachment.image, sistem secara otomatis merender halaman pertama dokumen. Namun untuk tampilan yang akurat, gunakan data langsung melalui inisialisator dengan data dan tipe 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)
Parameter ofType menerima string UTI (Uniform Type Identifier). Tipe standar: public.image (gambar apa pun), public.jpeg, public.png, com.adobe.pdf. Saat menentukan UTI yang benar, sistem memilih metode rendering yang tepat — untuk PDF adalah CGPDFDocument, untuk gambar — CGImageSource.
Untuk tipe file kustom (misalnya grafis vektor dalam format SVG) diperlukan subkelas NSTextAttachment yang menimpa metode image(forBounds:textContainer:characterIndex:). Jika rendering standar tidak sesuai, kembalikan nil dan implementasikan penggambaran melalui Core Graphics dalam metode draw.
NSTextAttachment bekerja dengan benar baik di UILabel maupun di UITextView. Namun UITextView memberikan lebih banyak kemampuan: interaksi dengan lampiran (mengetuk ikon), mengedit teks bersama dengan gambar, dan dukungan NSAttachmentBehavior.
Untuk menangani ketukan pada NSTextAttachment di UITextView, digunakan delegasi UITextViewDelegate dan metode textView(_:shouldInteractWith:in:interaction:). Metode ini dipanggil ketika pengguna mengetuk lampiran dan memungkinkan navigasi ke layar, membuka popup, atau memutar animasi.
func textView(_ textView: UITextView,
shouldInteractWith attachment: NSTextAttachment,
in characterRange: NSRange,
interaction: UITextItemInteraction) -> Bool {
if interaction == .preview {
return false
}
// Buka layar detail
showImageDetail(attachment.image)
return false
}
Metode ini membedakan tipe interaksi melalui parameter interaction: .preview (3D Touch / Haptic Touch), .default (ketukan biasa), dan .presentActions (menu konteks). Untuk setiap tipe Anda dapat mengatur perilaku sendiri atau melarangnya dengan mengembalikan false.
Saat mengedit UITextView dengan NSTextAttachment, penting untuk diingat: menghapus karakter pengganti (0xFFFC) juga menghapus lampiran. Pengguna melihat gambar sebagai satu kesatuan, dipilih secara keseluruhan, bukan piksel per piksel. Untuk dukungan seret dan lepas lampiran di iOS 15+ gunakan NSTextAttachmentViewProvider.
Kesalahan umum pertama — mengabaikan bounds. Pengembang sering mengandalkan ukuran asli gambar, yang mengakibatkan ikon raksasa di teks atau, sebaliknya, gambar yang hampir tidak terlihat. Selalu atur bounds secara eksplisit dengan mempertimbangkan font dan konteks.
Kesalahan kedua — pergeseran Y yang salah. Nilai positif di bounds.origin.y menurunkan gambar (dalam sistem koordinat UIKit sumbu Y mengarah ke bawah, ini tampak tidak logis tetapi begitulah cara Core Graphics bekerja). Untuk perataan ke tengah baris, gunakan rumus dengan capHeight font, seperti yang ditunjukkan di bagian 3.
Masalah ketiga — hilangnya gambar saat perubahan traitCollection. Ketika pengguna mengganti Dark Mode atau Dynamic Type, ukuran font dapat berubah sementara bounds tetap sama. Solusi — hitung bounds secara dinamis dalam metode layoutSubviews atau melalui KVO pada font.
Kesalahan umum keempat — menggunakan NSTextAttachment di UILabel dengan numberOfLines > 1. Dalam mode multi-baris dengan lebar terbatas, TextKit dengan benar memindahkan baris bersama dengan gambar. Masalah muncul ketika tinggi lampiran melebihi tinggi baris, baris yang berdekatan saling tumpang tindih. Solusi — tingkatkan lineSpacing melalui NSMutableParagraphStyle.
Pertanyaan yang Sering Diajukan
NSTextAttachment menjadikan gambar bagian dari aliran teks: ia berpindah, merata, dan diskalakan bersama teks. UIImageView terikat pada koordinat superview dan tidak berpartisipasi dalam tata letak teks.
Ya, jika Anda mengatur properti attributedText sebagai ganti text. UILabel menampilkan NSTextAttachment dengan benar, tetapi tidak mendukung interaktivitas. Untuk mengetuk lampiran gunakan UITextView.
Ubah properti bounds dari instance NSTextAttachment yang ada. Teks secara otomatis akan dirender ulang dengan ukuran baru tanpa perlu membuat NSAttributedString baru.
NSTextAttachment mendukung gambar statis. Untuk GIF dan format animasi diperlukan implementasi kustom melalui NSTextAttachmentViewProvider di iOS 15+ atau melalui CADisplayLink.
Buat instance NSTextAttachment, atur image atau data, tetapkan bounds, bungkus dalam NSAttributedString(attachment:) dan masukkan ke NSMutableAttributedString melalui metode insert(_:at:).
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga