Attributed Text هو آلية من SDK لـ iOS، تمثلها الفئتان NSAttributedString و NSMutableAttributedString، وتسمح بتطبيق أنماط متعددة على أجزاء مختلفة من نص واحد. بالخلاف عن NSString العادي، فإن Attributed String يخزن ليس فقط المحارف ولكن أيضًا قاموسًا من السمات لكل نطاق: الخط، اللون، تباعد السطور، الظل، والمحاذاة. وفقًا لـ وثائق Apple للمطورين، يعد Attributed String أساسًا لعرض النصوص المنسقة في UILabel و UITextView و UITextField. إنه الطريقة القياسية لتنسيق النصوص بدون WebKit أو مكتبات خارجية.
النقاط الرئيسية
NSAttributedString هي فئة من إطار Foundation تمثل سلسلة من السمات المسمّاة المرتبطة بنطاقات المحارف. كل سمة هي زوج مفتاح-قيمة: المفتاح محدّد بثابت (NSFontAttributeName، NSForegroundColorAttributeName)، والقيمة هي الكائن المقابل (UIFont، UIColor). تطبّق السمات على نطاق من المحارف عبر NSRange.
الفئة متاحة على جميع منصات Apple: iOS (2.0+)، macOS، tvOS، watchOS. NSAttributedString غير قابل للتغيير — بمجرد إنشائه، تكون سماته ثابتة. للتغيير الديناميكي، يستخدم NSMutableAttributedString، الذي يرث من NSAttributedString ويضيف الميثودات setAttributes، addAttributes، addAttribute، removeAttribute.
NSString هو سلسلة بسيطة من المحارف دون معلومات تنسيق. أي نص يتم إرساله إلى UILabel عبر text يظهر بخط واحد ولون وحجم واحد. NSAttributedString، المرسل عبر attributedText، يسمح لكل محرف بأن يكون له مجموعته الخاصة من السمات. UILabel، UITextView و UITextField يتعرفون تلقائيًا على NSAttributedString ويعرضون النص وفقًا لسماته.
داخليًا، يخزن NSAttributedString NSString مع النص ومصفوفة من نطاقات السمات. كل نطاق يُمثّل بهيكل NSRange وقاموس سمات. أثناء العرض، يتنقّل النظام عبر النطاقات ويطبّق السمات المقابلة على كل قسم. تعتمد الكفاءة على عدد تبديلات السمات — التغييرات المتكررة على أقسام قصيرة تزيد من وقت العرض.
سمات NSAttributedString هي ثوابت معرّفة في UIKit (iOS) و AppKit (macOS)، كل منها تتوافق مع جانب محدّد من التنسيق المرئي للنص. جميع السمات هي سلاسل NSAttributedString.Key، وقيمها هي كائنات من فئات محدّدة. تنقسم السمات إلى سمات على مستوى المحرف (تؤثر على المحارف) وسمات على مستوى الفقرة (تؤثر على الفقرات).
تشمل السمات على مستوى المحرف الخط (NSFontAttributeName)، لون النص (NSForegroundColorAttributeName)، لون الخلفية (NSBackgroundColorAttributeName)، التسطير (NSUnderlineStyleAttributeName)، الشطب (NSStrikethroughStyleAttributeName)، الظل (NSShadowAttributeName). تُعيّن السمات على مستوى الفقرة عبر NSParagraphStyleAttributeName، الذي يتحكم في المحاذاة، المسافة البادئة، تباعد السطور والجدولة.
NSLinkAttributeName يُنشئ رابطًا قابلًا للنقر في النص: القيمة هي URL أو سلسلة. UITextView يتعامل تلقائيًا مع هذه الروابط إذا كان التفاعل مُمكنًا. NSAttachmentAttributeName يسمح باحتواء NSTextAttachment — صورة داخل النص تظهر كعنصر مضمّن. يستخدم هذا لإنشاء نصوص بأيقونات أو رموز تعبيرية أو عروض مخصصة داخل السلسلة.
كل سمة من NSAttributedString لها قيمة مكتوبة بصرامة. لننظر إلى السمات الأكثر استخدامًا في تطوير iOS. يتم تعيين الخط عبر كائن UIFont، واللون عبر UIColor، وتباعد السطور عبر NSMutableParagraphStyle، الذي يسمح بتكوين المحاذاة، المسافة البادئة والتباعد في كائن واحد.
| مفتاح السمة | نوع القيمة | الغرض |
|---|---|---|
| NSFontAttributeName | UIFont | خط النص |
| NSForegroundColorAttributeName | UIColor | لون النص |
| NSBackgroundColorAttributeName | UIColor | لون الخلفية خلف النص |
| NSUnderlineStyleAttributeName | NSNumber (Int) | نمط التسطير |
| NSParagraphStyleAttributeName | NSParagraphStyle | إعدادات الفقرة |
| NSKernAttributeName | NSNumber (Float) | تباعد الأحرف |
NSParagraphStyle هو حاوية لسمات الفقرة: alignment، lineSpacing، paragraphSpacing، firstLineHeadIndent، lineBreakMode، minimumLineHeight وغيرها. لتعديل هذه المعلمات، يتم إنشاء NSMutableParagraphStyle، تعيين الخصائص المطلوبة، ويتم إرسال الكائن كقيمة سمة NSParagraphStyleAttributeName. هذه هي الطريقة الوحيدة للتحكم في تباعد السطور في NSAttributedString.
NSShadow يسمح بإضافة ظل للنص: تحدد المعلمات shadowOffset، shadowBlurRadius، shadowColor إزاحة الظل وتموجه ولونه. تقبل سمات التسطير والشطب تركيبات من الأنماط: NSUnderlineStyle.single، .double، .thick، .patternDash، .patternDot. للتحكم الدقيق في سمك الخطوط ولونها، يُستخدمان NSUnderlineColorAttributeName و NSStrikethroughColorAttributeName.
يتم إنشاء NSAttributedString في Swift عبر مهيئ مع النص وقاموس السمات، أو عبر NSMutableAttributedString مع تطبيق تدريجي للأنماط. النهج الأساسي هو تعريف قاموس سمات للنص بأكمله، ثم إضافة أو تعديل السمات لنطاقات محددة.
مثال بسيط — تعيين الخط، اللون والمحاذاة للسلسلة بأكملها. يتم إرسال قاموس السمات إلى مهيئ NSAttributedString. مفاتيح القاموس هي ثوابت NSAttributedString.Key، والقيم هي كائنات UIKit المقابلة. هذا هو الحالة الأساسية عندما يتم تنسيق النص بأكمله بشكل موحّد.
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 16),
.foregroundColor: UIColor.darkGray,
.paragraphStyle: let style = NSMutableParagraphStyle()
style.alignment = .center
style.lineSpacing = 4
return style
]
let attributedString = NSAttributedString(
string: "Hello world",
attributes: attributes
)
label.attributedText = attributedString
سيظهر النص بخط systemFont 16، لون رمادي داكن، محاذاة وسطية وتباعد سطور 4pt. هذا النهج مناسب للعناوين والأزرار الثابتة.
NSMutableAttributedString يسمح بتطبيق أنماط مختلفة على أجزاء مختلفة من النص. الميثود addAttribute يضيف سمة واحدة إلى نطاق، addAttributes يضيف قاموس سمات. الميثود setAttributes يستبدل جميع السمات الموجودة في النطاق بأخرى جديدة. هذه هي الأداة الرئيسية لإنشاء نص بتمييزات.
let text = "Price: 1999 rubles"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.foregroundColor,
value: UIColor.green, range: NSRange(location: 6, length: 4))
attributed.addAttribute(.font,
value: UIFont.boldSystemFont(ofSize: 20), range: NSRange(location: 6, length: 4))
label.attributedText = attributed
ستكون الكلمة «1999» باللون الأخضر والخط العريض، وباقي النص سيكون قياسيًا. يتم حساب NSRange يدويًا — من المهم حساب الطول بالأحرف بشكل صحيح، خاصة عند العمل مع الرموز التعبيرية والمحارف المركبة في Unicode.
NSMutableAttributedString يوفّر ميثودات لتغيير النص والسمات بشكل ديناميكي: append، insert، replace، delete، setAttributes، addAttribute، removeAttribute، enumerateAttributes. يسمح هذا ببناء نص من مصادر مختلفة، والجمع بين الأنماط، والاستجابة لأحداث الواجهة.
على عكس NSAttributedString غير القابل للتغيير، تدعم النسخة القابلة للتغيير تغيير المحتوى دون إنشاء كائن جديد. هذا أساسي لمحرررات النصوص، والدردشة، والنماذج حيث يمكن للمستخدم تحرير النص ويجب الحفاظ على الأنماط.
في تطبيقات المراسلة، يحتوي كل رسالة على اسم المستخدم (خط عريض)، نص الرسالة (عادي)، الوقت (لون رمادي). يسمح NSMutableAttributedString ببناء هذه السلسلة في مرة واحدة بإضافة الأجزاء بالترتيب المطلوب مع السمات المناسبة.
let result = NSMutableAttributedString()
let name = NSAttributedString(string: "Anna: ",
attributes: [.font: UIFont.boldSystemFont(ofSize: 15)])
let message = NSAttributedString(string: "Hello, how are you?",
attributes: [.font: UIFont.systemFont(ofSize: 15)])
let time = NSAttributedString(string: " 12:30",
attributes: [.foregroundColor: UIColor.gray])
result.append(name)
result.append(message)
result.append(time)
label.attributedText = result
النتيجة هي سلسلة واحدة بثلاثة أقسام منسقة. Append يحسب NSRange تلقائيًا، وليس هناك حاجة لحساب المواقع يدويًا. يتوسع هذا النهج لأي عدد من الأجزاء.
الميثود enumerateAttributes(in:options:using:) يمر عبر جميع نطاقات السمات في الفترة المحدّدة. هذا مفيد لتحليل التنسيق: العثور على جميع الروابط، تغيير لون سمات محددة أو تصدير النص إلى HTML. يتم إرسال قاموس السمات و NSRange للقسم الحالي إلى الإغلاق.
جميع مكونات واجهة المستخدم الرئيسية لعرض النص في UIKit تدعم NSAttributedString عبر خاصية attributedText. UILabel يعرض نصًا منسقًا ثابتًا، UITextView يدعم التحرير والروابط، UITextField يقبل سمات للنص الواضح والنص المدخل بشكل منفصل.
UILabel هو المكون الأخف لعرض النص المنسق. يدعم جميع سمات المحارف ولكنه لا يتعامل مع الروابط القابلة للنقر تلقائيًا (يلزم UITextView لذلك). UILabel مثالي للعناوين، التسميات والنصوص القصيرة المنسقة.
UITextView يتعامل مع NSLinkAttributeName ويعرض الروابط كعناصر تفاعلية. لتفعيل هذه الوظيفة، قم بتعيين isSelectable = true و isEditable = false. عند النقر على رابط، يتلقّى المفوّض استدعاء textView(_:shouldInteractWith:in:interaction:). UITextView يدعم أيضًا NSTextAttachment للصور داخل النص.
let text = "Details on developer.apple.com"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.link,
value: URL(string: "https://developer.apple.com")!,
range: NSRange(location: 0, length: text.count))
textView.attributedText = attributed
textView.isSelectable = true
textView.isEditable = false
بعد تعيين isSelectable و isEditable، تتصرف منطقة النص ككتلة نص ثابتة، ولكن الروابط تبقى نشطة. UITextViewDelegate يتحكم في السلوك عند النقر.
Core Text هو إطار منخفض المستوى من Apple لعرض النصوص يعمل مباشرة مع NSAttributedString. بالخلاف عن UIKit، لا يستخدم Core Text NSAttributedString مباشرة ككائن عرض — بل يحوّله إلى CTFramesetter، ثم CTFrame، ويعرضه في سياق Core Graphics. يمنح هذا تحكمًا كاملًا في ترتيب السطور والحروف.
يتبرر استخدام Core Text لتصميمات النص المخصصة: الأعمدة، التفاف حول الصور، تدوير النص، فصول السطور غير القياسية. يتضمن NSMutableParagraphStyle لـ Core Text سمات غير موجودة في UIKit: kCTParagraphStyleSpecifierMaximumLineSpacing، kCTParagraphStyleSpecifierLineBreakMode بأوضاع إضافية.
NSAttributedString ينتقل بسلاسة بين UIKit و Core Text، حيث يعمل كلا الإطارين مع نفس النوع. سمات UIKit (NSFontAttributeName، NSForegroundColorAttributeName) يتعرف عليها Core Text تلقائيًا، وبالعكس — سمات Core Text (kCTFontAttributeName) يقرأها UIKit. يسمح هذا باستخدام UIKit للمهام البسيطة و Core Text للعرض المخصص على نفس كائن NSAttributedString.
الأسئلة الشائعة
NSString يخزن النص فقط دون معلومات تنسيق. NSAttributedString يُكمّل النص بقاموس سمات لكل نطاق من المحارف. عند إرساله إلى UILabel عبر خاصية text، يظهر NSString كنص عادي. عند إرسال NSAttributedString عبر attributedText، تطبّق جميع السمات: خطوط مختلفة وألوان وتباعدات في سلسلة واحدة.
استخدم الميثود addAttributes(_:range:) مع قاموس سمات: addAttributes([.font: font, .foregroundColor: color], range: range). لإضافة أو تغيير سمة واحدة، استخدم addAttribute(_:value:range:). الميثود setAttributes يستبدل جميع السمات الموجودة في النطاق بالسمات المرسلة.
أنشئ NSMutableParagraphStyle، ضبط خاصية lineSpacing، ثم أرسله كقيمة سمة NSParagraphStyleAttributeName. للتحكم الكامل، تتوفر أيضًا minimumLineHeight، maximumLineHeight، paragraphSpacing، lineBreakMode و alignment. ParagraphStyle هو الطريقة الوحيدة للتحكم في تباعد السطور.
نعم، SwiftUI يدعم NSAttributedString عبر Text(attributedString:) في iOS 15+. في الإصدارات الأقدم، استخدم UIViewRepresentable مع UILabel أو UITextView. يوفّر SwiftUI أيضًا نوعه الخاص AttributedString (SwiftUI، ليس Foundation) للتنسيق التصريحي ببنية شبيهة بـ Markdown.
استخدم الميثود boundingRect(with:options:context:)، الذي يرجع CGRect اللازم لعرض السلسلة مع السمات المعطاة. تأخذ المعلمات options: [.usesLineFragmentOrigin, .usesFontLeading] في الحسبان تباعد السطور ومقاييس الخط. لـ UILabel بعدد محدود من السطور، استخدم sizeThatFits.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.