NSTextAttachment হল UIKit ফ্রেমওয়ার্কের একটি ক্লাস যা NSAttributedString-এর মাধ্যমে ফরম্যাট করা টেক্সটে ইমেজ এবং অন্যান্য মিডিয়া অবজেক্ট এম্বেড করার অনুমতি দেয়। এটি TextKit এবং Core Text স্তরে কাজ করে, ডেভেলপারদের টেক্সট প্রবাহের মধ্যে অ্যাটাচমেন্টের আকার, অবস্থান এবং আচরণের উপর নিয়ন্ত্রণ দেয়। Apple Documentation (2025) অনুযায়ী, NSTextAttachment ইমেজ, PDF এবং কাস্টম ভিউ কন্টেইনার সমর্থন করে, যা UITextView এবং UILabel-এর সাথে সংহত হয়। iOS অ্যাপ্লিকেশনে Rich Text তৈরি করার জন্য এই API বোঝা প্রয়োজনীয় — চ্যাট এবং এডিটর থেকে শুরু করে ক্যাপশনে আইকন সহ নিউজ ফিড পর্যন্ত।
মূল পয়েন্ট
NSTextAttachment হল UIKit ফ্রেমওয়ার্কের একটি ক্লাস যা মিডিয়া অবজেক্ট সরাসরি NSAttributedString-এর টেক্সট বিষয়বস্তুতে এম্বেড করার অনুমতি দেয়। টেক্সটের পাশে রাখা আলাদা UIImageView-এর বিপরীতে, NSTextAttachment ইমেজকে টেক্সট প্রবাহের অংশ করে তোলে: ইমেজ লাইনের সাথে চলে, সারিবদ্ধকরণে অংশ নেয় এবং একটি সাধারণ অক্ষরের মতো জায়গা নেয়।
এই ক্লাসটি TextKit আর্কিটেকচারের অংশ, যা iOS এবং macOS-এ টেক্সট রেন্ডারিং পরিচালনা করে। TextKit টেক্সটকে গ্লিফে ভাঙ্গে, কার্নিং, লিগেচার এবং লিডিং বিবেচনা করে — এবং NSTextAttachment এই পাইপলাইনে একটি বিশেষ অক্ষর হিসেবে ফিট করে যা একটি অক্ষর হিসেবে নয় বরং একটি গ্রাফিক অবজেক্ট হিসেবে রেন্ডার হয়।
প্রতিটি NSTextAttachment ইনস্ট্যান্সে contents (ফাইল ডেটা), fileType (UTI বিষয়বস্তুর ধরন), এবং bounds (পয়েন্টে একটি আয়তক্ষেত্র যা আকার এবং অবস্থান নির্ধারণ করে) থাকে। Apple Human Interface Guidelines অনুযায়ী, bounds ডিফল্টভাবে ইমেজের আকারের সমান, কিন্তু ফন্টের সাথে সঠিক ফিটের জন্য পরিবর্তন করা যেতে পারে।
NSTextAttachment আলাদা UIImageView-এর পরিবর্তে ব্যবহার করুন যখন ইমেজটি টেক্সটের অংশ হিসেবে আচরণ করা উচিত — চ্যাট, নিউজ ফিড, টেক্সট এডিটর এবং ইনপুট ফিল্ডে আইকন সহ ফর্মে।
NSTextAttachment-এর সাথে মৌলিক কর্মপ্রবাহ তিনটি ধাপ নিয়ে গঠিত: একটি ইনস্ট্যান্স তৈরি করুন, ইমেজ সেট করুন এবং এটি NSAttributedString-এর সাথে সংযুক্ত করুন। আসুন 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 প্রপার্টি থেকে ইমেজটি তার জায়গায় আঁকা হয়।
যদি ইমেজটি টেক্সট লাইনের মাঝখানে স্থাপন করা উচিত (উদাহরণস্বরূপ, একটি শব্দের পরে আইকন), কেবল NSMutableAttributedString-এ পছন্দসই অবস্থানে attachmentString সন্নিবেশ করুন। TextKit স্বয়ংক্রিয়ভাবে লাইনের উচ্চতা বিবেচনা করবে এবং বেসলাইনে ইমেজ সারিবদ্ধ করবে।
গুরুত্বপূর্ণ: image প্রপার্টি শুধুমাত্র iOS-এ উপলব্ধ (iOS 7 থেকে)। macOS-এ, NSImage-এর সাথে contents প্রপার্টি ব্যবহার করুন। পশ্চাৎগামী সামঞ্জস্যের জন্য, ডেটা কন্টেইনারের উপর নির্ভর না করে সর্বদা সরাসরি image সেট করতে পছন্দ করুন।
ডিফল্টভাবে, NSTextAttachment ইমেজটি পয়েন্টে মূল আকারে প্রদর্শন করে। বাস্তবে, প্রায় সবসময় আকার এবং উল্লম্ব অবস্থান সামঞ্জস্য করার প্রয়োজন হয় — এটি bounds প্রপার্টি ব্যবহার করে করা হয়।
CGRect bounds স্ট্রাকচারে origin (X এবং Y দ্বারা অফসেট) এবং size (প্রস্থ এবং উচ্চতা) অন্তর্ভুক্ত। Y অফসেট বিশেষভাবে গুরুত্বপূর্ণ: একটি নেতিবাচক মান ইমেজকে বেসলাইনের নীচে নামিয়ে দেয়, একটি ইতিবাচক মান এটি উপরে তোলে। একটি সাধারণ পরিস্থিতি হল টেক্সট লাইনের কেন্দ্রে একটি আইকন সারিবদ্ধ করা।
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 অফসেট শূন্যে।
NSTextAttachment শুধুমাত্র PNG এবং JPEG নয়, PDF ডকুমেন্টের পাশাপাশি contents প্রপার্টির মাধ্যমে নির্বিচারে ফাইলও সমর্থন করে। এটি iOS অ্যাপ্লিকেশনে Rich Text-এর জন্য একটি সার্বজনীন টুল করে তোলে।
attachment.image-এ PDF ইমেজ সেট করার সময়, সিস্টেম স্বয়ংক্রিয়ভাবে ডকুমেন্টের প্রথম পৃষ্ঠা রেন্ডার করে। তবে, সঠিক রেন্ডারিংয়ের জন্য, ডেটা এবং 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)
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 ফেরত দিন এবং draw পদ্ধতিতে Core Graphics-এর মাধ্যমে ড্রয়িং বাস্তবায়ন করুন।
NSTextAttachment UILabel এবং UITextView উভয়েই সঠিকভাবে কাজ করে। তবে, UITextView আরও ক্ষমতা প্রদান করে: অ্যাটাচমেন্টের সাথে ইন্টারঅ্যাকশন (আইকনে ট্যাপ করা), ইমেজ সহ টেক্সট সম্পাদনা, এবং NSAttachmentBehavior-এর জন্য সমর্থন।
UITextView-এ NSTextAttachment-এ ট্যাপ হ্যান্ডেল করার জন্য, UITextViewDelegate প্রোটোকল এবং textView(_:shouldInteractWith:in:interaction:) পদ্ধতি ব্যবহার করুন। এই পদ্ধতিটি কল করা হয় যখন ব্যবহারকারী একটি অ্যাটাচমেন্ট ট্যাপ করে এবং একটি স্ক্রিনে নেভিগেট করতে, পপআপ খুলতে বা অ্যানিমেশন চালানোর অনুমতি দেয়।
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 ফেরত দিয়ে এটি নিষ্ক্রিয় করতে পারেন।
NSTextAttachment সহ UITextView সম্পাদনা করার সময়, এটি মনে রাখা গুরুত্বপূর্ণ: রিপ্লেসমেন্ট ক্যারেক্টার (0xFFFC) মুছে ফেললে অ্যাটাচমেন্টও মুছে যায়। ব্যবহারকারী ইমেজটিকে একটি একক উপাদান হিসেবে দেখেন — এটি সম্পূর্ণরূপে নির্বাচিত হয়, পিক্সেল বাই পিক্সেল নয়। iOS 15+-এ অ্যাটাচমেন্টের ড্র্যাগ-এন্ড-ড্রপ সমর্থনের জন্য, NSTextAttachmentViewProvider ব্যবহার করুন।
প্রথম সাধারণ ভুল হল bounds উপেক্ষা করা. ডেভেলপাররা প্রায়ই মূল ইমেজের আকারের উপর নির্ভর করে, যার ফলে টেক্সটে বিশাল আইকন বা, বিপরীতভাবে, সবে দৃশ্যমান ইমেজ হয়। সর্বদা ফন্ট এবং প্রসঙ্গ বিবেচনা করে bounds স্পষ্টভাবে সেট করুন।
দ্বিতীয় ভুল হল ভুল Y অফসেট. bounds.origin.y-তে একটি ইতিবাচক মান ইমেজকে নীচে নামিয়ে দেয় (UIKit-এর কোঅর্ডিনেট সিস্টেমে, Y অক্ষ নীচের দিকে নির্দেশ করে — এটি অসংগতিপূর্ণ মনে হয়, কিন্তু Core Graphics এইভাবেই কাজ করে)। একটি লাইনের মধ্যে কেন্দ্র-সারিবদ্ধ করার জন্য, সেকশন 3-এ দেখানো হিসাবে ফন্টের capHeight সহ সূত্র ব্যবহার করুন।
তৃতীয় সমস্যা হল traitCollection পরিবর্তনে ইমেজ হারানো. যখন ব্যবহারকারী ডার্ক মোড বা Dynamic Type পরিবর্তন করে, ফন্টের আকার পরিবর্তন হতে পারে, কিন্তু bounds একই থাকে। সমাধান হল layoutSubviews পদ্ধতিতে বা ফন্টে KVO-এর মাধ্যমে bounds গতিশীলভাবে গণনা করা।
চতুর্থ ঘন ঘন ভুল হল numberOfLines > 1 সহ UILabel-এ NSTextAttachment ব্যবহার করা. সীমিত প্রস্থ সহ মাল্টিলাইন মোডে, TextKit ইমেজ সহ লাইনগুলি সঠিকভাবে মোড়ায়। সমস্যা দেখা দেয় যখন অ্যাটাচমেন্টের উচ্চতা লাইনের উচ্চতা অতিক্রম করে — সংলগ্ন লাইনগুলি একে অপরকে ওভারল্যাপ করে। সমাধান হল NSMutableParagraphStyle-এর মাধ্যমে lineSpacing বাড়ানো।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
NSTextAttachment ইমেজকে টেক্সট প্রবাহের অংশ করে তোলে: এটি টেক্সটের সাথে চলে, সারিবদ্ধ হয় এবং স্কেল হয়। UIImageView সুপারভিউ কোঅর্ডিনেটের সাথে আবদ্ধ এবং টেক্সট লেআউটে অংশ নেয় না।
হ্যাঁ, যদি আপনি text-এর পরিবর্তে attributedText প্রপার্টি সেট করেন। UILabel সঠিকভাবে NSTextAttachment প্রদর্শন করে কিন্তু ইন্টারঅ্যাকটিভিটি সমর্থন করে না। অ্যাটাচমেন্টে ট্যাপের জন্য, UITextView ব্যবহার করুন।
বিদ্যমান NSTextAttachment ইনস্ট্যান্সের bounds প্রপার্টি পরিবর্তন করুন। নতুন NSAttributedString তৈরি করার প্রয়োজন ছাড়াই টেক্সট স্বয়ংক্রিয়ভাবে নতুন আকারে পুনরায় রেন্ডার হবে।
NSTextAttachment স্থির ইমেজ সমর্থন করে। GIF এবং অ্যানিমেটেড ফরম্যাটের জন্য, iOS 15+-এ NSTextAttachmentViewProvider বা CADisplayLink-এর মাধ্যমে কাস্টম বাস্তবায়ন প্রয়োজন।
একটি NSTextAttachment ইনস্ট্যান্স তৈরি করুন, ইমেজ বা ডেটা সেট করুন, bounds সেট করুন, এটি NSAttributedString(attachment:) এ মোড়ান এবং insert(_:at:) পদ্ধতি ব্যবহার করে NSMutableAttributedString-এ সন্নিবেশ করুন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন