UIFont / CTFont — این چیست، انواع فونت و Core Text

نویسنده: IT Sectr منتشر شده: 2026-07-23 زمان مطالعه: 9 دقیقه

UIFont و CTFont — کلاس‌هایی برای کار با فونت‌ها در iOS هستند: UIFont از UIKit برای پیکربندی سطح بالای متن در UILabel و UITextView، CTFont از Core Text برای رندر سطح پایین با کنترل کامل بر گلیف‌ها و متریک‌ها. طبق Apple Developer Documentation، UIFont در 90% کامپوننت‌های استاندارد UI استفاده می‌شود، در حالی که CTFont در موتورهای متنی سفارشی و ویرایشگرها به کار می‌رود. هر دو کلاس یک فونت را اما در سطوح مختلف انتزاع نمایش می‌دهند.

نکات اصلی

  • UIFont — کلاس سطح بالای UIKit برای کار با فونت‌ها در کامپوننت‌های UI
  • CTFont — کلاس سطح پایین Core Text برای کنترل دقیق بر تایپوگرافی
  • UIFont از طریق systemFont، preferredFont یا initWithName ساخته می‌شود، CTFont — از طریق CTFontCreateWithName
  • Dynamic Type — سیستم فونت‌های تطبیقی iOS که به طور خودکار به تنظیمات دسترسی واکنش نشان می‌دهد
  • CTFont دسترسی مستقیم به متریک‌های گلیف، کرنینگ و جداول OpenType فراهم می‌کند

UIFont و CTFont چیستند؟

UIFont — کلاس UIKit است که فونت را برای نمایش متن در کامپوننت‌های UI نمایش می‌دهد: UILabel، UITextView، UITextField. این کلاس رابط ساده‌ای برای دریافت فونت‌های سیستمی و سفارشی با تعیین اندازه، وزن و سبک فراهم می‌کند. UIFont اجازه مدیریت مستقیم کرنینگ، لیگاتورها و ویژگی‌های OpenType را نمی‌دهد — برای این کار از Core Text استفاده می‌شود.

CTFont — نوع Core Text (CTFontRef) است که دسترسی سطح پایین به داده‌های فونت را فراهم می‌کند. CTFont مستقیماً با Core Graphics برای رندر کار می‌کند، از تمام قابلیت‌های OpenType و TrueType از جمله گلیف‌های جایگزین، لیگاتورها و فونت‌های متغیر پشتیبانی می‌کند. CTFont در داخل UIKit برای رندر UIFont استفاده می‌شود، اما برای ترسیم سفارشی نیز مستقیماً در دسترس است.

پل زنی بدون هزینه (Toll-Free Bridging)

UIFont و CTFont از toll-free bridging — تبدیل بین انواع بدون هزینه اضافی پشتیبانی می‌کنند. تبدیل (cast) UIFont as CTFont یا CTFont as UIFont در Swift و Objective-C امکان‌پذیر است. این اجازه می‌دهد از API سطح بالای UIKit برای پیکربندی و Core Text سطح پایین برای رندر بدون کپی کردن داده‌های فونت استفاده کنید.

توصیف‌گر فونت (Font Descriptor)

هر دو کلاس از UIFontDescriptor (UIKit) / CTFontDescriptor (Core Text) برای توصیف ویژگی‌های فونت استفاده می‌کنند: نام، اندازه، وزن، سبک، ماتریس تبدیل. Descriptor یک فرهنگ لغت از ویژگی‌ها است که می‌توان آن را تغییر داد و فونت‌های جدیدی بر اساس فونت‌های موجود ایجاد کرد. مثلاً traitItalic را به descriptor اضافه کرده و نسخه ایتالیک همان فونت را دریافت کنید.

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 اضافه شده و در bundle برنامه گنجانده شود. به گفته Apple، توصیه می‌شود برای تمام کامپوننت‌های استاندارد UI از UIFont استفاده کنید و فقط در صورت نیاز به رندر سفارشی به CTFont مهاجرت کنید.

تایپ پویا (Dynamic Type)

Dynamic Type — سیستم فونت‌های تطبیقی معرفی شده در iOS 7. کاربر اندازه متن ترجیحی خود را در تنظیمات انتخاب می‌کند — از بسیار کوچک تا بسیار بزرگ. UIFont.preferredFont به طور خودکار فونت با اندازه مناسب را برمی‌گرداند. برای کار صحیح، تمام UILabelها باید adjustsFontForContentSizeCategory = true داشته باشند. Dynamic Type برای سازگاری با دسترسی اجباری است.

UIFontDescriptor

UIFontDescriptor امکان تغییر ویژگی‌های فونت را بدون ایجاد نمونه جدید از صفر فراهم می‌کند. متدهای addingAttributes(_:)، withSymbolicTraits(_:)، withFamily(_:) یک descriptor جدید با پارامترهای تغییر یافته برمی‌گردانند. این برای دریافت انواع فونت مفید است: افزودن traitBold به فونت سیستمی و دریافت نسخه پررنگ بدون دانستن نام PostScript.

CTFont — فونت‌های Core Text

CTFont (CTFontRef) — نوع Core Text برای کار سطح پایین با فونت‌ها است. با توابع CTFontCreateWithName، CTFontCreateWithFontDescriptor، CTFontCreateCopyWithAttributes ایجاد می‌شود. هر تابع فونتی با واسط، اندازه و ویژگی‌های اختیاری مشخص شده برمی‌گرداند. CTFont در Core Graphics برای رندر متن در UIViewهای سفارشی از طریق drawRect استفاده می‌شود.

CTFont دسترسی به متریک‌هایی را فراهم می‌کند که در UIFont موجود نیستند: CTFontGetGlyphsForCharacters آرایه‌ای از گلیف‌ها برای کاراکترهای داده شده برمی‌گرداند، CTFontGetAdvancesForGlyphs — عرض هر گلیف، CTFontGetBoundingBox — مرزهای گلیف. این برای ساخت layoutهای متنی سفارشی ضروری است: ستون‌ها، چرخش، جریان.

متریک‌های فونت

CTFontGetAscent، CTFontGetDescent، CTFontGetLeading متریک‌های عمودی فونت را برمی‌گردانند. CTFontGetUnitsPerEm — تعداد واحدها در em-square، برای محاسبه نسبت‌ها استفاده می‌شود. CTFontGetGlyphCount — تعداد کل گلیف‌ها در فونت. این داده‌ها برای تایپوگرافی چاپی و صفحه‌بندی‌های سفارشی که نیاز به موقعیت‌یابی دقیق هر کاراکتر دارند، حیاتی هستند.

OpenType و فونت‌های متغیر

CTFont از ویژگی‌های OpenType پشتیبانی می‌کند: CTFontCopyFeatures فرهنگ لغت توابع موجود فونت را برمی‌گرداند (لیگاتورها، کاراکترهای جایگزین، کرنینگ)، CTFontEnableFeature گزینه خاصی را فعال می‌کند. فونت‌های متغیر (Variable Fonts) از طریق 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 کش می‌شوند، بنابراین ایجاد مجدد فونت سیستمی هزینه اضافی ندارد.

فونت سفارشی از Bundle

برای استفاده از فونت سفارشی، فایل TTF یا OTF را به bundle پروژه اضافه کنید و آن را در 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("\(خانواده): \(نام‌ها)")
}
// بارگذاری فونت سفارشی
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+ فونت باشد، نیازی به گنجاندن همه آنها در bundle اولیه نیست، بلکه می‌توان در اولین استفاده آنها را دانلود کرد. CTFontManagerRegisterFontsForURLs فونت‌ها را از URLهای مشخص شده ثبت می‌کند. پس از ثبت، فونت مانند همیشه از طریق UIFont(name:size:) در دسترس است.

CTFontCreateWithName برای فونت سفارشی

برای رندر سفارشی از طریق Core Text از CTFontCreateWithName با نام PostScript فونت استفاده کنید. تفاوت با UIFont این است که CTFont می‌تواند با ماتریس تبدیل ایجاد شود (CTFontCreateWithNameAndOptions) — برای ایجاد فونت‌های تحریف شده: کج کردن، مقیاس در محور X، چرخش. این بدون استفاده از تبدیل‌های affine در 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)
// استفاده از toll-free bridging با UIFont
let uiFont = ctFont as UIFont
label.font = uiFont

ماتریس تبدیل امکان ایجاد انواع italic را بدون فایل جداگانه فونت فراهم می‌کند. پارامتر c (skew) به حروف کجی اضافه می‌کند. ماتریس همچنین امکان مقیاس افقی فونت را فراهم می‌کند — ایجاد انواع فشرده یا گسترده از همان فونت.

تفاوت‌های UIFont و CTFont

تفاوت اصلی بین UIFont و CTFont سطح انتزاع است. UIFont API ساده‌ای برای وظایف رایج فراهم می‌کند: دریافت فونت سیستمی، تغییر اندازه، اعمال به UILabel. CTFont کنترل کامل بر فونت را ارائه می‌دهد: دسترسی به گلیف‌ها، متریک‌ها، جداول OpenType و محورهای متغیر. انتخاب بستگی به وظیفه دارد.

ویژگیUIFontCTFont
فریمورکUIKitCore Text
ایجادsystemFont / preferredFont / initWithNameCTFontCreateWithName / CTFontCreateWithDescriptor
دسترسی به گلیف‌هاخیرCTFontGetGlyphsForCharacters
ویژگی‌های OpenTypeمحدود (UIFontDescriptor)دسترسی کامل
فونت‌های متغیراز طریق UIFontDescriptorCTFontCopyVariation / CreateCopyWithVariation
رندرخودکار در کامپوننت‌های UICore 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 از toll-free bridging پشتیبانی می‌کنند. تبدیل با یک کست ساده انجام می‌شود: UIFont as CTFont یا CTFont as UIFont. هیچ هزینه اضافی یا کپی داده‌ای رخ نمی‌دهد — هر دو کلاس به یک شیء فونت در حافظه اشاره می‌کنند.

کدام یک برای استفاده در UIKit ترجیح داده می‌شود؟

برای تمام کامپوننت‌های UI از 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. با این حال، API UIFont برای فونت‌های متغیر در مقایسه با CTFontCopyVariation محدود است. برای کنترل کامل بر محورهای متغیر از Core Text و CTFontCreateCopyWithVariation استفاده کنید.

چگونه UIFont را به درستی کش کنیم؟

یک فرهنگ لغت استاتیک یا NSCache با کلید ترکیبی از نام و اندازه ایجاد کنید. برای فونت‌های سیستمی، iOS نمونه‌ها را به طور خودکار کش می‌کند، اما برای فونت‌های سفارشی ایجاد شده از طریق UIFont(name:size:)، توصیه می‌شود اشیاء را در کش برنامه ذخیره کنید تا از بارگذاری مجدد از فایل TTF جلوگیری شود.

خلاصه

  • UIFont — کلاس سطح بالای UIKit برای فونت‌ها در کامپوننت‌های UI با Dynamic Type
  • CTFont — نوع سطح پایین Core Text برای رندر و دسترسی به گلیف‌ها
  • UIFont از طریق systemFont، preferredFont یا UIFont(name:size:) ایجاد می‌شود
  • CTFont از طریق CTFontCreateWithName یا CTFontCreateWithDescriptor ایجاد می‌شود
  • Toll-free bridging امکان تبدیل رایگان UIFont به CTFont و بالعکس را فراهم می‌کند
  • Dynamic Type برای دسترسی اجباری است: از preferredFont و adjustsFontForContentSizeCategory استفاده کنید
  • برای UIKit از UIFont، برای رندر سفارشی — از CTFont استفاده کنید

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید