UIFont / CTFont — ما هو، أنواع الخطوط و Core Text

المؤلف: IT Sectr نُشر: 2026-07-23 وقت القراءة: 9 دق

UIFont و CTFont هما فئتان للعمل مع الخطوط في iOS: UIFont من UIKit لإعداد النص عالي المستوى في UILabel و UITextView، CTFont من Core Text للعرض منخفض المستوى مع تحكم كامل في الرموز الرسومية والمقاييس. وفقاً لوثائق Apple Developer، يُستخدم UIFont في 90% من مكونات واجهة المستخدم القياسية، بينما يُستخدم CTFont في محركات النص المخصصة والمحررات. تمثل كلتا الفئتين خطاً واحداً ولكن بمستوى مختلف من التجريد.

النقاط الرئيسية

  • UIFont — فئة عالية المستوى من UIKit للعمل مع الخطوط في مكونات واجهة المستخدم
  • CTFont — فئة منخفضة المستوى من Core Text للتحكم الدقيق في الطباعة
  • UIFont يُنشأ عبر systemFont أو preferredFont أو initWithName، CTFont — عبر CTFontCreateWithName
  • Dynamic Type — نظام خطوط تكيفي في iOS يستجيب تلقائياً لإعدادات إمكانية الوصول
  • CTFont يوفر وصولاً مباشراً إلى مقاييس الرموز الرسومية والترقيق وجداول OpenType

ما هما UIFont و CTFont؟

UIFont هي فئة UIKit تمثل خطاً لعرض النص في مكونات واجهة المستخدم: UILabel و UITextView و UITextField. توفر واجهة بسيطة للحصول على خطوط النظام والخطوط المخصصة مع تحديد الحجم والوزن والنمط. لا يسمح UIFont بالتحكم المباشر في الترقيم والربط وميزات OpenType — لذلك يُستخدم Core Text.

CTFont هو نوع Core Text (CTFontRef) يوفر وصولاً منخفض المستوى لبيانات الخط. يعمل CTFont مباشرة مع Core Graphics للعرض، ويدعم جميع ميزات OpenType و TrueType بما في ذلك الرموز الرسومية البديلة والربط والخطوط المتغيرة. يُستخدم CTFont داخلياً بواسطة UIKit لعرض UIFont، لكنه متاح أيضاً مباشرة للرسم المخصص.

الجسر الحر (Toll-Free Bridging)

يدعم UIFont و CTFont الجسر الحر — التحويل بين الأنواع دون تكلفة إضافية. تحويل UIFont إلى CTFont أو CTFont إلى UIFont ممكن في Swift و Objective-C. يتيح ذلك استخدام واجهة برمجة التطبيقات عالية المستوى من UIKit للإعداد و Core Text منخفض المستوى للعرض دون نسخ بيانات الخط.

وصف الخط

تستخدم كلتا الفئتين UIFontDescriptor (UIKit) / CTFontDescriptor (Core Text) لوصف خصائص الخط: الاسم والحجم والوزن والنمط ومصفوفة التحويل. الواصف هو قاموس سمات يمكن تعديله لإنشاء خطوط جديدة بناءً على الخطوط الموجودة. على سبيل المثال، إضافة traitItalic إلى واصف للحصول على نسخة مائلة من نفس الخط.

UIFont — خطوط UIKit

UIFont يوفر عدة طرق مصنعية لإنشاء الخطوط. systemFont(ofSize:) يعيد خط النظام San Francisco (iOS) أو Helvetica (الإصدارات الأقدم). boldSystemFont، italicSystemFont — متغيرات بأنماط محددة. preferredFont(forTextStyle:) يعيد خط Dynamic Type للنمط المحدد: .headline، .body، .caption1، .footnote. يتم تحجيم هذه الخطوط تلقائياً عند تغيير إعدادات حجم النص في النظام.

لتحميل الخطوط المخصصة، يُستخدم UIFont(name:size:) مع اسم PostScript للخط. يجب إضافة الخط أولاً إلى Info.plist وتضمينه في حزمة التطبيق. وفقاً لـ Apple، يُنصح باستخدام UIFort لجميع مكونات واجهة المستخدم القياسية والتحول إلى CTFont فقط عند الحاجة إلى عرض مخصص.

Dynamic Type

Dynamic Type هو نظام خطوط تكيفي تم تقديمه في iOS 7. يختار المستخدم حجم النص المفضل لديه في الإعدادات — من صغير جداً إلى كبير جداً. يعيد UIFont.preferredFont تلقائياً خطاً بالحجم المناسب. للتشغيل الصحيح، يجب أن تحتوي جميع UILabel على adjustsFontForContentSizeCategory = true. Dynamic Type إلزامي للتوافق مع إمكانية الوصول.

UIFontDescriptor

UIFontDescriptor يسمح بتعديل سمات الخط دون إنشاء مثيل جديد من الصفر. الطرق addingAttributes(_:)، withSymbolicTraits(_:)، withFamily(_:) تعيد واصفاً جديداً بمعلمات معدلة. هذا مناسب للحصول على متغيرات الخط: إضافة traitBold إلى خط النظام للحصول على نسخة عريضة دون معرفة اسم PostScript.

CTFont — خطوط Core Text

CTFont (CTFontRef) هو نوع Core Text للعمل منخفض المستوى مع الخطوط. يُنشأ بواسطة CTFontCreateWithName و CTFontCreateWithFontDescriptor و CTFontCreateCopyWithAttributes. كل دالة تعيد خطاً بالواجهة والحجم والسمات الاختيارية المحددة. يُستخدم CTFont في Core Graphics لعرض النص على UIView مخصص عبر drawRect.

يوفر CTFont الوصول إلى مقاييس غير متوفرة في UIFont: CTFontGetGlyphsForCharacters يعيد مصفوفة من الرموز الرسومية لأحرف معينة، CTFontGetAdvancesForGlyphs — عرض كل رمز رسومي، CTFontGetBoundingBox — حدود الرمز الرسومي. هذا ضروري لبناء تخطيطات نص مخصصة: أعمدة، تدوير، التفاف.

مقاييس الخط

CTFontGetAscent و CTFontGetDescent و CTFontGetLeading تعيد المقاييس الرأسية للخط. CTFontGetUnitsPerEm — عدد الوحدات لكل em-square، يُستخدم لحساب النسب. CTFontGetGlyphCount — العدد الإجمالي للرموز الرسومية في الخط. هذه البيانات حاسمة للطباعة المطبعية والتخطيطات المخصصة حيث يتطلب تحديد موضع دقيق لكل حرف.

OpenType والخطوط المتغيرة

CTFont يدعم ميزات OpenType: CTFontCopyFeatures يعيد قاموساً للوظائف المتاحة للخط (الربط والأحرف البديلة والترقيق)، CTFontEnableFeature ينشط خياراً محدداً. يتم تكوين الخطوط المتغيرة عبر CTFontCopyVariation و CTFontCreateCopyWithVariation، مما يسمح بتغيير weight و width و slant في نطاق مستمر.

كيفية استخدام UIFont في الكود

يتم إنشاء UIFont في Swift من خلال إحدى الطرق المصنعية أو التهيئة المباشرة بالاسم. الطريقة الأكثر شيوعاً هي systemFont(ofSize:weight:) لخطوط النظام أو preferredFont(forTextStyle:) لـ Dynamic Type. للخطوط المخصصة، يُستخدم UIFont(name:size:) مع تحديد اسم PostScript.

خط النظام بأوزان مختلفة

يقبل UIFont.systemFont(ofSize:weight:) UIFont.Weight — من .ultraLight إلى .black. تعيد هذه الطريقة خط النظام San Francisco بالوزن المقابل. UIFont.monospacedSystemFont، UIFont.monospacedDigitSystemFont يعيدان خطوط أحادية المسافة للكود والأرقام. جميع خطوط النظام تدعم Dynamic Type تلقائياً.

swift
let regularFont = UIFont.systemFont(ofSize: 16, weight: .regular)
let boldFont = UIFont.systemFont(ofSize: 16, weight: .bold)
let headlineFont = UIFont.preferredFont(forTextStyle: .headline)
let monoFont = UIFont.monospacedSystemFont(ofSize: 14, weight: .regular)
label.font = headlineFont

يمكن تعيين كل خط مباشرة لخاصية font في UILabel أو استخدامه في NSAttributedString عبر NSFontAttributeName. يتم تخزين خطوط النظام في ذاكرة التخزين المؤقت بواسطة iOS، لذلك فإن إعادة إنشاء خط النظام لا تسبب أي حمل إضافي.

خط مخصص من الحزمة

لاستخدام خط مخصص، أضف ملف TTF أو OTF إلى حزمة المشروع وحدده في Info.plist (UIAppFonts). يمكن العثور على اسم PostScript للخط عبر UIFont.familyNames و UIFont.fontNames(forFamilyName:). بعد التسجيل، يصبح الخط متاحاً عبر UIFont(name:size:) من أي مكان في التطبيق.

swift
// الحصول على جميع أسماء عائلات الخطوط
for family in UIFont.familyNames {
    let names = UIFont.fontNames(forFamilyName: family)
    print("\(family): \(names)")
}
// تحميل خط مخصص
if let customFont = UIFont(name: "MyCustomFont-Regular", size: 18) {
    label.font = customFont
}

إذا تم تحديد اسم الخط بشكل غير صحيح، يعيد UIFont(name:size:) قيمة nil. يُنصح بطباعة جميع أسماء الخطوط المتاحة عبر UIFont.familyNames و UIFont.fontNames(forFamilyName:) أثناء التصحيح للتأكد من تسجيل الخط بشكل صحيح.

الخطوط المخصصة مع UIFont و CTFont

تحميل الخطوط المخصصة ممكن بطريقتين: التسجيل الثابت عبر Info.plist (UIAppFonts) والتسجيل الديناميكي عبر CTFontManagerRegisterGraphicsFont. الطريقة الأولى أبسط — الخط متاح فوراً بعد بدء التطبيق. الثانية تُستخدم للخطوط التي يتم تنزيلها من الشبكة أو الموارد عند الطلب.

التسجيل الديناميكي مفيد للموارد عند الطلب: إذا كان التطبيق يحتوي على 20+ خطاً، يمكن استبعادها جميعاً من الحزمة الأولية وتنزيلها عند الاستخدام الأول. يسجل CTFontManagerRegisterFontsForURLs الخطوط من عناوين URL المحددة. بعد التسجيل، يصبح الخط متاحاً عبر UIFont(name:size:) كالمعتاد.

CTFontCreateWithName للخط المخصص

للعرض المخصص عبر Core Text، استخدم CTFontCreateWithName مع اسم PostScript للخط. الفرق مع UIFont هو أنه يمكن إنشاء CTFont بمصفوفة تحويل (CTFontCreateWithNameAndOptions) — لإنشاء خطوط مشوهة: إمالة، تغيير مقياس المحور X، تدوير. هذا غير متاح في UIFont دون استخدام تحويلات أفينية.

swift
// إنشاء CTFont بمصفوفة إمالة
var matrix = CGAffineTransform(a: 1, b: 0, c: 0.2, d: 1, tx: 0, ty: 0)
let ctFont = CTFontCreateWithName(
    "Helvetica" as CFString,
    24, &matrix)
// استخدام الجسر الحر مع UIFont
let uiFont = ctFont as UIFont
label.font = uiFont

مصفوفة التحويل تسمح بإنشاء متغيرات مائلة بدون ملف خط منفصل. المعامل c (skew) يضيف إمالة للأحرف. تسمح المصفوفة أيضاً بتغيير مقياس الخط أفقياً — لإنشاء متغيرات مضغوطة أو موسعة من نفس الخط.

الاختلافات بين UIFont و CTFont

الفرق الرئيسي بين UIFont و CTFont هو مستوى التجريد. يوفر UIFont واجهة برمجة تطبيقات بسيطة للمهام الشائعة: الحصول على خط النظام، تغيير الحجم، التطبيق على UILabel. يوفر CTFont تحكماً كاملاً في الخط: الوصول إلى الرموز الرسومية والمقاييس وجداول OpenType والمحاور المتغيرة. يعتمد الاختيار على المهمة.

الخاصيةUIFontCTFont
الإطارUIKitCore Text
الإنشاءsystemFont / preferredFont / initWithNameCTFontCreateWithName / CTFontCreateWithDescriptor
الوصول إلى الرموز الرسوميةلاCTFontGetGlyphsForCharacters
ميزات OpenTypeمحدود (UIFontDescriptor)وصول كامل
الخطوط المتغيرةعبر UIFontDescriptorCTFontCopyVariation / CreateCopyWithVariation
العرضتلقائي في مكونات واجهة المستخدمCore Graphics، مخصص

لـ 95% من مهام تطوير iOS، UIFont كافٍ. Core Text مع CTFont مبرر عند إنشاء محررات النص ومولدات PDF والكتب ذات التخطيط الطباعي أو التطبيقات ذات العرض المخصص للغات النادرة.

الأداء وأفضل الممارسات

يتطلب العمل مع الخطوط في iOS مراعاة الأداء. يتم تحميل كل خط فريد في الذاكرة عند أول وصول ويستهلك موارد. خطوط النظام San Francisco محملة مسبقاً ولا تسبب حملاً إضافياً. يتم تحميل الخطوط المخصصة من الملف وتخزينها مؤقتاً بواسطة النظام بعد التحميل الأول.

يُنصح <بتحديد عدد الخطوط الفريدة

في التطبيق من 3 إلى 5 عائلات. يشغل كل خط من 50 كيلوبايت إلى 2 ميجابايت في الذاكرة. استخدام أوزان مختلفة من نفس العائلة (regular، bold، medium) أكثر كفاءة من تحميل عدة عائلات مختلفة.

تخزين UIFont المؤقت

يقوم النظام بتخزين مثيلات UIFont التي تم إنشاؤها مؤقتاً، لذلك فإن الاستدعاءات المتكررة لـ UIFont.systemFont(ofSize: 16, weight: .regular) لا تنشئ كائناً جديداً. ومع ذلك، فإن UIFont(name:size:) للخطوط المخصصة لا يتم تخزينه مؤقتاً دائماً — يُنصح بحفظ الخطوط المستخدمة بكثرة في خصائص ثابتة أو NSCache لتجنب إعادة التحميل من الملف.

تحميل الخطوط غير المتزامن

عند تسجيل الخطوط ديناميكياً عبر CTFontManagerRegisterGraphicsFont، يمكن أن تكون العملية غير متزامنة إذا تم تنزيل ملف الخط من الشبكة. في هذه الحالة، يجب أن يعرض UILabel أو UITextView خط نظام احتياطياً حتى اكتمال التحميل. بعد التسجيل، يصبح الخط متاحاً وتقوم الشاشة بتحديث عرض النص تلقائياً.

الأسئلة الشائعة

هل يمكن تحويل UIFont إلى CTFont والعكس؟

نعم، يدعم UIFont و CTFont الجسر الحر. يتم التحويل عن طريق تحويل بسيط: UIFont إلى CTFont أو CTFont إلى UIFont. لا يحدث أي حمل إضافي أو نسخ بيانات — تشير كلتا الفئتين إلى نفس كائن الخط في الذاكرة.

أيهما مفضل للاستخدام في UIKit؟

لجميع مكونات واجهة المستخدم، استخدم UIFont. إنه محسّن لـ UIKit ويدعم Dynamic Type ويتم تحجيمه بشكل صحيح عند تغيير إعدادات النظام. CTFont مبرر فقط للعرض المخصص عبر Core Graphics أو عند الحاجة إلى الوصول إلى مقاييس الخط منخفضة المستوى.

كيفية معرفة اسم الخط لـ UIFont(name:size:)؟

استخدم UIFont.familyNames لقائمة العائلات و UIFont.fontNames(forFamilyName:) لأسماء PostScript. قم باستدعاء هذا الكود في وضع التصحيح وابحث عن الخط المطلوب. يحتوي اسم PostScript عادة على اسم العائلة والنمط: «SFProText-Regular»، «HelveticaNeue-Bold».

هل يدعم UIFont الخطوط المتغيرة؟

نعم، من خلال UIFontDescriptor يمكن تكوين المحاور المتغيرة: weight، width، slant. ومع ذلك، فإن واجهة برمجة تطبيقات UIFont للخطوط المتغيرة محدودة مقارنة بـ CTFontCopyVariation. للتحكم الكامل في المحاور المتغيرة، استخدم Core Text و CTFontCreateCopyWithVariation.

كيفية تخزين UIFont مؤقتاً بشكل صحيح؟

أنشئ قاموساً ثابتاً أو NSCache بمفتاح يجمع الاسم والحجم. بالنسبة لخطوط النظام، يخزن iOS المثيلات مؤقتاً تلقائياً، ولكن بالنسبة للخطوط المخصصة التي تم إنشاؤها عبر UIFont(name:size:)، يُنصح بحفظ الكائنات في ذاكرة التخزين المؤقت للتطبيق لتجنب إعادة التحميل من ملف TTF.

الخلاصة

  • UIFont — فئة عالية المستوى من UIKit للخطوط في مكونات واجهة المستخدم مع Dynamic Type
  • CTFont — نوع منخفض المستوى من Core Text للعرض والوصول إلى الرموز الرسومية
  • UIFont يُنشأ عبر systemFont أو preferredFont أو UIFont(name:size:)
  • CTFont يُنشأ عبر CTFontCreateWithName أو CTFontCreateWithDescriptor
  • الجسر الحر يسمح بالتحويل المجاني بين UIFont و CTFont
  • Dynamic Type إلزامي لإمكانية الوصول: استخدم preferredFont و adjustsFontForContentSizeCategory
  • لـ UIKit استخدم UIFont، للعرض المخصص استخدم CTFont

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا