NSTextAttachment: คืออะไรและวิธีเพิ่มรูปภาพในข้อความบน iOS

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-07-25 เวลาอ่าน: 9 นาที

NSTextAttachment เป็นคลาสจาก framework UIKit ที่ช่วยให้สามารถฝังรูปภาพและวัตถุสื่อต่าง ๆ ลงในข้อความที่ได้รับการจัดรูปแบบผ่าน NSAttributedString มันทำงานในระดับ TextKit และ Core Text ทำไห้นักพัฒนาสามารถควบคุมขนาด ตำแหน่ง และพฤติกรรมของสิ่งแนบภายในกระแสข้อความ ตาม Apple Documentation (2025) NSTextAttachment รองรับรูปภาพ PDF และคอนเทนเนอร์มุมมองที่กำหนดเอง โดยผสานกับ UITextView และ UILabel การทำความเข้าใจ API นี้จำเป็นสำหรับการสร้าง Rich Text ในแอพพลิเคชัน iOS ตั้งแต่แชทและโปรแกรมแก้ไขข้อความไปจนถึงฟีดข่าวที่มีไอคอนในคำอธิบาย

ประเด็นสำคัญ

  • NSTextAttachment เป็นคลาส UIKit สำหรับฝังสื่อในข้อความที่ได้รับการจัดรูปแบบ iOS
  • รูปภาพถูกเพิ่มผ่าน NSAttributedString ด้วยคีย์ NSAttachmentAttributeName
  • คุณสมบัติ bounds ควบคุมขนาดและการเลื่อนแนวตั้งของสิ่งแนบ
  • NSTextAttachment รองรับ รูปภาพ PDF และไฟล์ที่กำหนดเองผ่านคอนเทนเนอร์ข้อมูล
  • API ผสานกับ UITextView UILabel และ TextKit สำหรับเลย์เอาต์ข้อความที่ยืดหยุ่น

NSTextAttachment คืออะไร?

NSTextAttachment เป็นคลาสจาก framework UIKit ที่ช่วยให้สามารถฝังวัตถุสื่อโดยตรงในเนื้อหาข้อความของ NSAttributedString แตกต่างจาก UIImageView แยกต่างที่วางไว้ใกล้ข้อความ NSTextAttachment ทำให้รูปภาพเป็นส่วนหนึ่งของกระแสข้อความ: รูปภาพจะตัดคำเป็นแนวเดียวกับบรรทัด มีส่วนร่วมในการจัดแนวสำหรับและใช้พื้นที่เหมือนกับอักขระทั่วไป

คลาสนี้เป็นส่วนหนึ่งของสถาปัตยกรรม TextKit ซึ่งจัดการเรอร์ข้อความบน iOS และ macOS TextKit แยกข้อความเป็นกลิฟ คำนึงถึงการเก็บระยะตัวอักษร การผูกตัวอักษรและการนำบรรทัด และ NSTextAttachment เข้ากับสายท่อนี้เป็นอักขระพิเศษที่เรอร์ไม่ใช่เป็นตัวอักษรแต่เป็นวัตถุกราฟิก

แต่ละอินสแตนซ์ NSTextAttachment ประกอบด้วย contents (ข้อมูลไฟล์) fileType (ชนิดเนื้อหา UTI) และ bounds (สี่เหลี่ยมมุมฉากในหน่วย points ที่กำหนดขนาดและตำแหน่ง) ตาม Apple Human Interface Guidelines bounds โดยค่าเริ่มต้นเท่ากับขนาดรูปภาพ แต่สามารถเปลี่ยนได้เพื่อให้เหมาะสมกับแบบอักษร

ใช้ NSTextAttachment แทน UIImageView แยกต่างเมื่อรูปภาพต้องทำตัวเองเป็นส่วนหนึ่งของข้อความ ในแชท ฟีดข่าว โปรแกรมแก้ไขข้อความ และแบฟอนที่มีไอคอนในช่องกรอกข้อมูล

วิธีเพิ่มรูปภาพในข้อความผ่าน NSTextAttachment

ขั้นตอนพื้นฐานของ NSTextAttachment ประกอบด้วยสามขั้นตอน: สร้างอินสแตนซ์ ตั้งค่ารูปภาพ และแนบไปยัง NSAttributedString มาดูกระบวนการโดยใช้ 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

หลังจากเรียกใช้ NSAttributedString(attachment:) วัตถุ NSTextAttachment จะถูกแปลงเป็นแอตทริบิวต์ NSAttachmentAttributeName ซึ่งแนบไปกับอักขระแทนที่วัตถุพิเศษ (รหัส 0xFFFC) อักขระนี้จะไม่แสดงเป็นตัวอักษร แต่จะวาดรูปภาพจากคุณสมบัติ image แทน

หากต้องวางรูปภาพไว้ตรงกลางบรรทัดข้อความ (เช่น ไอคอนหลังคำ) เพียงแทรก attachmentString ในตำแหน่งที่ต้องการใน NSMutableAttributedString TextKit จะพิจารณาความสูงของบรรทัดโดยอัตโนมัติและจัดตำแหน่งรูปภาพที่เส้นฐาน

สำคัญ: คุณสมบัติ image มีให้ใช้เฉพาะบน iOS (ตั้งแต่ iOS 7) บน macOS ให้ใช้คุณสมบัติ contents กับ NSImage สำหรับความเข้ากันได้กับเวอร์ชันก่อนหน้า ควรตั้งค่า image โดยตรงเสมอไปแทนที่จะพึ่งพาคอนเทนเนอร์ข้อมูล

การกำหนดค่า bounds และตำแหน่งของสิ่งแนบ

โดยค่าเริ่มต้น NSTextAttachment จะแสดงรูปภาพใน ขนาดต้นฉบับ เป็น points ในทางปฏิบัติ เกือบทุกครั้งจะต้องปรับขนาดและตำแหน่งแนวตั้ง โดยใช้คุณสมบัติ bounds

โครงสร้าง CGRect bounds ประกอบด้วย origin (การเลื่อนเบื่องตาม X และ Y) และ size (ความกว้างและความสูง) การเลื่อนเบื่องตาม Y มีความสำคัญเฉพาะ: ค่าลบจะลดรูปภาพลงได้เส้นฐาน ค่าบวกจะยกขึ้น สถานการณ์ทั่วไปคือการจัดไอคอนให้อยู่กลางบรรทัดข้อความ

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
)

การคำนวณการจัดตำแหน่งใช้ capHeight ของแบบอักษร ความสูงของตัวพิมพ์ใหญ่ ไม่ใช่ความสูงเต็มของบรรทัด ซึ่งช่วยให้ไอคอนตรงกับขอบบนของข้อความ แทนที่จะลอยระหว่างเส้นฐานและส่วนยื่น ขนาดรูปภาพในตัวอย่างคือ 18×18 pt ซึ่งเป็นขนาดทั่วไปสำหรับไอคอนในข้อความ UI

หากรูปภาพต้องใหญ่กว่าบรรทัดข้อความ (เช่น การแสดงตัวอย่างรูปภาพในแชท) TextKit จะเพิ่มช่องว่างระหว่างบรรทัดโดยอัตโนมัติสำหรับบรรทัดปัจจุบัน ในกรณีนี้ ควรตั้ง bounds เป็นขนาดธรรมชาติ และตั้งค่าเลื่อนเบื่องตาม Y เป็นศูนย์

PDF และสิ่งแนบที่กำหนดเอง

NSTextAttachment รองรับไม่เฉพาะ PNG และ JPEG แต่ยังรองรับเอกสาร PDF รวมถึงไฟล์ใด ๆ ผ่านคุณสมบัติ contents ทำให้มันเป็นเครื่องมือสากสำหรับ Rich Text ในแอพพลิเคชัน iOS

เมื่อตั้งค่ารูปภาพ PDF ใน attachment.image ระบบจะเรอร์หน้าแรกของเอกสารโดยอัตโนมัติ อย่างไรก็ตาม สำหรับการเรอร์ที่แม่นยำ ให้ใช้ข้อมูลโดยตรงผ่านตัวเริ่มต้นที่มีข้อมูลและชนิด 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)

พารามิเตอร์ ofType รับสตริง UTI (Uniform Type Identifier) ชนิดมาตรฐานไม้แก่ public.image (รูปภาพใด ๆ), public.jpeg, public.png, com.adobe.pdf เมื่อระบุ UTI ที่ถูกต้อง ระบบจะเลือกวิธีการเรอร์ที่เหมาะสม สำหรับ PDF คือ CGPDFDocument สำหรับรูปภาพคือ CGImageSource

สำหรับไฟล์ประเภทที่กำหนดเอง (เช่น กราฟิกเวกเตอร์ในรูปแบบ SVG) คุณจะต้องใช้คลาสย่อยของ NSTextAttachment ที่เกินค่าเมธอด image(forBounds:textContainer:characterIndex:) หากการเรอร์มาตรฐานไม่เหมาะสม ให้คืน nil และดำเนินการวาดผ่าน Core Graphics ในเมธอด draw

NSTextAttachment ใน UITextView และการมอบหมาย

NSTextAttachment ทำงานได้อย่างถูกต้องทั้งใน UILabel และ UITextView อย่างไรก็ตาม UITextView มีความสามารถมากขึ้น: การโต้ตอบกับสิ่งแนบ (แตะไอคอน) การแก้ไขข้อความพร้อมกับรูปภาพ และการรองรับ NSAttachmentBehavior

เพื่อจัดการแตะบน NSTextAttachment ใน UITextView ให้ใช้โปรโตคอล UITextViewDelegate และเมธอด textView(_:shouldInteractWith:in:interaction:) เมธอดนี้จะถูกเรียกเมื่อผู้ใช้แตะสิ่งแนบและช่วยให้สามารถเปิดหน้าจอ เปิดป๊อปอัป หรือเล่นแอนิเมชัน

swift
func textView(_ textView: UITextView,
                shouldInteractWith attachment: NSTextAttachment,
                in characterRange: NSRange,
                interaction: UITextItemInteraction) -> Bool {
    if interaction == .preview {
        return false
    }
    // เปิดหน้าจอรายละเอียด
    showImageDetail(attachment.image)
    return false
}

เมธอดจะแยกแยะประเภทการโต้ตอผ่านพารามิเตอร์ interaction: .preview (3D Touch / Haptic Touch), .default (แตะปกติ) และ .presentActions (เมนูบริบท) สำหรับแต่ละประเภท คุณสามารถกำหนดพฤติกรรมของตนเองหรือปิดใช้โดยคืน false

เมื่อแก้ไข UITextView ที่มี NSTextAttachment สิ่งสำคัญที่ต้องจำคือ: การลบอักขระทดแทน (0xFFFC) จะลบสิ่งแนบด้วย ผู้ใช้จะเห็นรูปภาพเป็นองค์ประกอบเดียว โดยจะถูกเลือกทั้งหมด ไม่ใช่ทีละพิกเซล สำหรับการรองรับลากและวางของสิ่งแนบบน iOS 15+ ให้ใช้ NSTextAttachmentViewProvider

ข้อผิดพลาดทั่วไปในการทำงานกับ NSTextAttachment

ข้อผิดพลาดที่พบบ่อยครั้งแรกคือการ ละเลย bounds นักพัฒนามักพึ่งพาขนาดรูปภาพต้นฉบับ ซึ่งนำไปสู่ไอคอนขนาดใหญ่ในข้อความหรือในทางกลับกัน รูปภาพที่แทบจะมองไม่เห็น กำหนด bounds อย่างชัดเจนโดยพิจารณาถึงแบบอักษรและบริบท

ข้อผิดพลาดที่สองคือการเลื่อนเบื่องตาม Y ที่ไม่ถูกต้อง ค่าบวกใน bounds.origin.y จะลดรูปภาพลง (ในระบบพิกัดของ UIKit แกน Y ชี้ลงด้านล่าง ซึ่งดูเหมือนขัดอย่าง แต่นี้คือวิธีทำงานของ Core Graphics) สำหรับการจัดกลางภายในบรรทัด ให้ใช้สูตรกับ capHeight ของแบบอักษรตามที่แสดงในส่วนที่ 3

ปัญหาที่สามคือการสูญเสียรูปภาพเมื่อเปลี่ยน traitCollection เมื่อผู้ใช้เปลี่ยนโหมดมืดหรือ Dynamic Type ขนาดแบบอักษรอาจเปลี่ยนแต่ bounds ยังเหมือนเดิม วิธีแก้คือคำนวณ bounds แบบไดนามิกในเมธอด layoutSubviews หรือผ่าน KVO บน font

ข้อผิดพลาดที่พบบ่อยครั้งที่สี่คือการใช้ NSTextAttachment ใน UILabel ที่มี numberOfLines > 1 ในโหมดหลายบรรทัดที่มีความกว้างจำกัด TextKit จะตัดคำเป็นแนวเดียวกับรูปภาพอย่างถูกต้อง ปัญหาเกิดขึ้นเมื่อความสูงของสิ่งแนบเกินความสูงของบรรทัด ทำให้บรรทัดใกล้เคียงกัน วิธีแก้คือการเพิ่ม lineSpacing ผ่าน NSMutableParagraphStyle

คำถามที่พบบ่อย

NSTextAttachment แตกต่างจาก UIImageView ในข้อความอย่างไร?

NSTextAttachment ทำให้รูปภาพเป็นส่วนหนึ่งของกระแสข้อความ: มันจะตัดคำเป็น จัดแนวและปรับขนาดไปกับข้อความ UIImageView ถูกผูกกับพิกัดของ superview และไม่มีส่วนร่วมในเลย์เอาต์ข้อความ

สามารถเพิ่ม NSTextAttachment ใน UILabel ได้หรือไม่?

ได้ หากคุณตั้งคุณสมบัติ attributedText แทน text UILabel แสดง NSTextAttachment ได้อย่างถูกต้อง แต่ไม่รองรับการโต้ตอบ สำหรับการแตะสิ่งแนบ ให้ใช้ UITextView

จะเปลี่ยนขนาดรูปภาพหลังจากสร้าง attachment ได้อย่างไร?

เปลี่ยนคุณสมบัติ bounds ของอินสแตนซ์ NSTextAttachment ที่มีอยู่ ข้อความจะถูกเรอร์ใหม่โดยอัตโนมัติด้วยขนาดใหม่ โดยไม่ต้องสร้าง NSAttributedString ใหม่

NSTextAttachment รองรับรูปภาพแอนิเมชันหรือไม่?

NSTextAttachment รองรับรูปภาพนิ่ง สำหรับ GIF และรูปแบบแอนิเมชัน จำเป็นต้องมีการดำเนินการแบบกำหนดเองผ่าน NSTextAttachmentViewProvider บน iOS 15+ หรือผ่าน CADisplayLink

จะเพิ่ม NSTextAttachment ในข้อความโดยโปรแกรมได้อย่างไร?

สร้างอินสแตนซ์ NSTextAttachment ตั้งค่ารูปภาพหรือข้อมูล กำหนด bounds ห่อใน NSAttributedString(attachment:) และใส่ใน NSMutableAttributedString โดยใช้ระบบเมธอด insert(_:at:)

สรุป

  • NSTextAttachment เป็นคลาส UIKit สำหรับการฝังรูปภาพ PDF และสื่ออื่น ๆ ในข้อความที่ได้รับการจัดรูปแบบ
  • รูปภาพถูกเพิ่มผ่าน NSAttributedString(attachment:) และกลายเป็นส่วนหนึ่งของกระแสข้อความ
  • คุณสมบัติ bounds ควบคุมขนาดและตำแหน่ง: ควรกำหนดอย่างชัดเจนโดยพิจารณาถึงแบบอักษร
  • หากต้องการจัดกลางไอคอนภายในบรรทัด ให้ใช้สูตรกับ capHeight ของแบบอักษรปัจจุบัน
  • รองรับการแนบ PDF ผ่านตัวเริ่มต้นที่มี data และชนิด UTI ที่ถูกต้อง
  • สำหรับการจัดการแตะสิ่งแนบ ให้ใช้ UITextViewDelegate และเมธอด shouldInteractWith
  • เมื่อ Dynamic Type เปลี่ยนแปลง ให้คำนวณ bounds ใหม่แบบไดนามิกเพื่อหลีกเลี่ยงการทับซ้อนของบรรทัด

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม