UIFont / CTFont — khái niệm, loại phông chữ và Core Text

Tác giả: IT Sectr Đã đăng: 2026-07-23 Thời gian đọc: 9 phút

UIFontCTFont là các lớp để làm việc với phông chữ trong iOS: UIFont từ UIKit để cấu hình văn bản cấp cao trong UILabel và UITextView, CTFont từ Core Text để render cấp thấp với kiểm soát hoàn toàn glyph và số liệu. Theo Apple Developer Documentation, UIFont được sử dụng trong 90% thành phần UI tiêu chuẩn, trong khi CTFont được sử dụng trong các engine văn bản tùy chỉnh và trình soạn thảo. Cả hai lớp đều biểu diễn một phông chữ nhưng ở mức độ trừu tượng khác nhau.

Những điểm chính

  • UIFont — lớp UIKit cấp cao để làm việc với phông chữ trong thành phần UI
  • CTFont — lớp Core Text cấp thấp để kiểm soát chính xác kiểu chữ
  • UIFont được tạo qua systemFont, preferredFont hoặc initWithName, CTFont — qua CTFontCreateWithName
  • Dynamic Type — hệ thống phông chữ thích ứng iOS tự động phản hồi cài đặt trợ năng
  • CTFont cung cấp truy cập trực tiếp đến số liệu glyph, kerning và bảng OpenType

UIFont và CTFont là gì?

UIFont là một lớp UIKit đại diện cho phông chữ để hiển thị văn bản trong thành phần UI: UILabel, UITextView, UITextField. Nó cung cấp giao diện đơn giản để lấy phông chữ hệ thống và tùy chỉnh với kích thước, trọng lượng và kiểu được chỉ định. UIFont không cho phép kiểm soát trực tiếp kerning, ligature và tính năng OpenType — Core Text được sử dụng cho việc đó.

CTFont là một kiểu Core Text (CTFontRef) cung cấp truy cập cấp thấp đến dữ liệu phông chữ. CTFont làm việc trực tiếp với Core Graphics để render, hỗ trợ tất cả tính năng OpenType và TrueType bao gồm glyph thay thế, ligature và phông chữ biến đổi. CTFont được UIKit sử dụng nội bộ để render UIFont nhưng cũng có sẵn trực tiếp cho vẽ tùy chỉnh.

Toll-Free Bridging

UIFont và CTFont hỗ trợ Toll-Free Bridging — chuyển đổi giữa các kiểu mà không tốn thêm chi phí. Ép kiểu UIFont as CTFont hoặc CTFont as UIFont có thể thực hiện trong Swift và Objective-C. Điều này cho phép sử dụng API cấp cao của UIKit để cấu hình và Core Text cấp thấp để render mà không sao chép dữ liệu phông chữ.

Bộ mô tả phông chữ

Cả hai lớp sử dụng UIFontDescriptor (UIKit) / CTFontDescriptor (Core Text) để mô tả đặc điểm phông chữ: tên, kích thước, trọng lượng, kiểu, ma trận biến đổi. Bộ mô tả là một từ điển thuộc tính có thể được sửa đổi để tạo phông chữ mới dựa trên phông chữ hiện có. Ví dụ, thêm traitItalic vào bộ mô tả và nhận phiên bản nghiêng của cùng một phông chữ.

UIFont — phông chữ UIKit

UIFont cung cấp một số phương thức factory để tạo phông chữ. systemFont(ofSize:) trả về phông chữ hệ thống San Francisco (iOS) hoặc Helvetica (phiên bản cũ). boldSystemFont, italicSystemFont — biến thể với kiểu cụ thể. preferredFont(forTextStyle:) trả về phông chữ Dynamic Type cho kiểu được chỉ định: .headline, .body, .caption1, .footnote. Các phông chữ này tự động co giãn khi cài đặt kích thước văn bản thay đổi trong hệ thống.

Để tải phông chữ tùy chỉnh, sử dụng UIFont(name:size:) với tên PostScript của phông chữ. Phông chữ phải được thêm vào Info.plist trước và bao gồm trong bundle ứng dụng. Theo Apple, khuyến nghị sử dụng UIFont cho tất cả thành phần UI tiêu chuẩn và chuyển sang CTFont chỉ khi cần render tùy chỉnh.

Dynamic Type

Dynamic Type là hệ thống phông chữ thích ứng được giới thiệu trong iOS 7. Người dùng chọn kích thước văn bản ưa thích trong Cài đặt — từ cực nhỏ đến cực lớn. UIFont.preferredFont tự động trả về phông chữ có kích thước phù hợp. Để hoạt động đúng, tất cả UILabel phải có adjustsFontForContentSizeCategory = true. Dynamic Type bắt buộc để tuân thủ trợ năng.

UIFontDescriptor

UIFontDescriptor cho phép sửa đổi thuộc tính phông chữ mà không tạo phiên bản mới từ đầu. Các phương thức addingAttributes(_:), withSymbolicTraits(_:), withFamily(_:) trả về bộ mô tả mới với tham số đã thay đổi. Điều này thuận tiện để lấy biến thể phông chữ: thêm traitBold vào phông chữ hệ thống và nhận phiên bản đậm mà không cần biết tên PostScript.

CTFont — phông chữ Core Text

CTFont (CTFontRef) là một kiểu Core Text để làm việc với phông chữ cấp thấp. Nó được tạo bởi CTFontCreateWithName, CTFontCreateWithFontDescriptor, CTFontCreateCopyWithAttributes. Mỗi hàm trả về một phông chữ với giao diện, kích thước và thuộc tính tùy chọn được chỉ định. CTFont được sử dụng trong Core Graphics để render văn bản trên UIView tùy chỉnh qua drawRect.

CTFont cung cấp truy cập đến số liệu không có trong UIFont: CTFontGetGlyphsForCharacters trả về mảng glyph cho các ký tự được chỉ định, CTFontGetAdvancesForGlyphs — chiều rộng của mỗi glyph, CTFontGetBoundingBox — ranh giới glyph. Điều này cần thiết để xây dựng bố cục văn bản tùy chỉnh: cột, xoay, ngắt dòng.

Số liệu phông chữ

CTFontGetAscent, CTFontGetDescent, CTFontGetLeading trả về số liệu dọc của phông chữ. CTFontGetUnitsPerEm — số lượng đơn vị trên em-vuông, được sử dụng để tính tỷ lệ. CTFontGetGlyphCount — tổng số glyph trong phông chữ. Dữ liệu này rất quan trọng cho kiểu chữ in ấn và bố cục tùy chỉnh nơi yêu cầu định vị chính xác từng ký tự.

OpenType và phông chữ biến đổi

CTFont hỗ trợ tính năng OpenType: CTFontCopyFeatures trả về từ điển các chức năng phông chữ có sẵn (ligature, ký tự thay thế, kerning), CTFontEnableFeature kích hoạt tùy chọn cụ thể. Phông chữ biến đổi được cấu hình qua CTFontCopyVariation và CTFontCreateCopyWithVariation, cho phép thay đổi weight, width và slant trong phạm vi liên tục.

Cách sử dụng UIFont trong mã

Việc tạo UIFont trong Swift được thực hiện qua một trong các phương thức factory hoặc khởi tạo trực tiếp bằng tên. Cách phổ biến nhất là systemFont(ofSize:weight:) cho phông chữ hệ thống hoặc preferredFont(forTextStyle:) cho Dynamic Type. Cho phông chữ tùy chỉnh, sử dụng UIFont(name:size:) với tên PostScript được chỉ định.

Phông chữ hệ thống với trọng lượng khác nhau

UIFont.systemFont(ofSize:weight:) chấp nhận UIFont.Weight — từ .ultraLight đến .black. Phương thức này trả về phông chữ hệ thống San Francisco với trọng lượng tương ứng. UIFont.monospacedSystemFont, UIFont.monospacedDigitSystemFont trả về phông chữ đơn cách cho mã và số. Tất cả phông chữ hệ thống tự động hỗ trợ 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

Mỗi phông chữ có thể được gán trực tiếp vào thuộc tính font của UILabel hoặc sử dụng trong NSAttributedString qua NSFontAttributeName. Phông chữ hệ thống được iOS lưu vào bộ nhớ đệm, vì vậy việc tạo lại phông chữ hệ thống không gây ra chi phí.

Phông chữ tùy chỉnh từ Bundle

Để sử dụng phông chữ tùy chỉnh, thêm tệp TTF hoặc OTF vào bundle dự án và chỉ định nó trong Info.plist (UIAppFonts). Tên PostScript của phông chữ có thể được tìm qua UIFont.familyNames và UIFont.fontNames(forFamilyName:). Sau khi đăng ký, phông chữ có sẵn qua UIFont(name:size:) từ bất kỳ đâu trong ứng dụng.

swift
// Lấy tất cả tên họ phông chữ
for family in UIFont.familyNames {
    let names = UIFont.fontNames(forFamilyName: family)
    print("\(family): \(names)")
}
// Tải phông chữ tùy chỉnh
if let customFont = UIFont(name: "MyCustomFont-Regular", size: 18) {
    label.font = customFont
}

Nếu tên phông chữ được chỉ định không chính xác, UIFont(name:size:) trả về nil. Khuyến nghị in tất cả tên phông chữ có sẵn qua UIFont.familyNames và UIFont.fontNames(forFamilyName:) trong quá trình gỡ lỗi để đảm bảo phông chữ được đăng ký chính xác.

Phông chữ tùy chỉnh với UIFont và CTFont

Tải phông chữ tùy chỉnh có thể thực hiện theo hai cách: đăng ký tĩnh qua Info.plist (UIAppFonts) và đăng ký động qua CTFontManagerRegisterGraphicsFont. Cách đầu tiên đơn giản hơn — phông chữ có sẵn ngay sau khi khởi động ứng dụng. Cách thứ hai được sử dụng cho phông chữ tải từ mạng hoặc tài nguyên theo yêu cầu.

Đăng ký động hữu ích cho tài nguyên theo yêu cầu: nếu ứng dụng chứa hơn 20 phông chữ, tất cả có thể được loại khỏi bundle ban đầu và tải xuống khi sử dụng lần đầu. CTFontManagerRegisterFontsForURLs đăng ký phông chữ từ các URL được chỉ định. Sau khi đăng ký, phông chữ có sẵn qua UIFont(name:size:) như bình thường.

CTFontCreateWithName cho phông chữ tùy chỉnh

Để render tùy chỉnh qua Core Text, sử dụng CTFontCreateWithName với tên PostScript của phông chữ. Sự khác biệt với UIFont là CTFont có thể được tạo với ma trận biến đổi (CTFontCreateWithNameAndOptions) — để tạo phông chữ biến dạng: nghiêng, co giãn trục X, xoay. Điều này không có sẵn trong UIFont nếu không sử dụng biến đổi affine.

swift
// Tạo CTFont với ma trận xiên
var matrix = CGAffineTransform(a: 1, b: 0, c: 0.2, d: 1, tx: 0, ty: 0)
let ctFont = CTFontCreateWithName(
    "Helvetica" as CFString,
    24, &matrix)
// Sử dụng Toll-Free Bridging với UIFont
let uiFont = ctFont as UIFont
label.font = uiFont

Ma trận biến đổi cho phép tạo biến thể nghiêng mà không cần tệp phông chữ riêng. Tham số c (skew) thêm độ nghiêng cho ký tự. Ma trận cũng cho phép co giãn phông chữ theo chiều ngang — tạo biến thể cô đọng hoặc mở rộng của một phông chữ.

Sự khác biệt giữa UIFont và CTFont

Sự khác biệt chính giữa UIFontCTFont là mức độ trừu tượng. UIFont cung cấp API đơn giản cho các tác vụ phổ biến: lấy phông chữ hệ thống, thay đổi kích thước, áp dụng cho UILabel. CTFont cung cấp kiểm soát hoàn toàn phông chữ: truy cập glyph, số liệu, bảng OpenType và trục biến đổi. Lựa chọn phụ thuộc vào tác vụ.

Đặc điểmUIFontCTFont
FrameworkUIKitCore Text
TạosystemFont / preferredFont / initWithNameCTFontCreateWithName / CTFontCreateWithDescriptor
Truy cập glyphKhôngCTFontGetGlyphsForCharacters
Tính năng OpenTypeGiới hạn (UIFontDescriptor)Truy cập đầy đủ
Phông chữ biến đổiQua UIFontDescriptorCTFontCopyVariation / CreateCopyWithVariation
RenderTự động trong thành phần UICore Graphics, tùy chỉnh

Đối với 95% tác vụ phát triển iOS, UIFont là đủ. Core Text với CTFont phù hợp khi tạo trình soạn thảo văn bản, trình tạo PDF, sách với bố cục kiểu chữ hoặc ứng dụng render tùy chỉnh ngôn ngữ hiếm.

Hiệu suất và thực hành tốt nhất

Làm việc với phông chữ trong iOS cần xem xét hiệu suất. Mỗi phông chữ duy nhất được tải vào bộ nhớ khi truy cập lần đầu và tiêu tốn tài nguyên. Phông chữ hệ thống San Francisco được tải sẵn và không tạo chi phí. Phông chữ tùy chỉnh được tải từ tệp và được hệ thống lưu vào bộ nhớ đệm sau lần tải đầu tiên.

Khuyến nghị giới hạn số lượng phông chữ duy nhất trong ứng dụng ở mức 3-5 họ. Mỗi phông chữ chiếm từ 50 KB đến 2 MB trong bộ nhớ. Sử dụng các trọng lượng khác nhau của cùng một họ (regular, bold, medium) hiệu quả hơn so với tải nhiều họ khác nhau.

Lưu đệm UIFont

Hệ thống lưu vào bộ nhớ đệm các phiên bản UIFont đã tạo, vì vậy các cuộc gọi lặp lại đến UIFont.systemFont(ofSize: 16, weight: .regular) không tạo đối tượng mới. Tuy nhiên, UIFont(name:size:) cho phông chữ tùy chỉnh không phải lúc nào cũng được lưu đệm — khuyến nghị lưu phông chữ thường dùng trong thuộc tính tĩnh hoặc NSCache để tránh tải lại từ tệp.

Tải phông chữ bất đồng bộ

Khi đăng ký phông chữ động qua CTFontManagerRegisterGraphicsFont, quá trình có thể bất đồng bộ nếu tệp phông chữ được tải từ mạng. Trong trường hợp này, UILabel hoặc UITextView nên hiển thị phông chữ hệ thống dự phòng cho đến khi tải hoàn tất. Sau khi đăng ký, phông chữ có sẵn và màn hình tự động cập nhật hiển thị văn bản.

Câu hỏi thường gặp

Có thể chuyển đổi UIFont thành CTFont và ngược lại không?

Có, UIFont và CTFont hỗ trợ Toll-Free Bridging. Việc chuyển đổi được thực hiện bằng ép kiểu đơn giản: UIFont as CTFont hoặc CTFont as UIFont. Không có chi phí hoặc sao chép dữ liệu — cả hai lớp đều trỏ đến cùng một đối tượng phông chữ trong bộ nhớ.

Cái nào được ưu tiên sử dụng trong UIKit?

Cho tất cả thành phần UI, sử dụng UIFont. Nó được tối ưu cho UIKit, hỗ trợ Dynamic Type và co giãn chính xác khi cài đặt hệ thống thay đổi. CTFont chỉ phù hợp cho render tùy chỉnh qua Core Graphics hoặc khi cần truy cập số liệu phông chữ cấp thấp.

Làm thế nào để tìm tên phông chữ cho UIFont(name:size:)?

Sử dụng UIFont.familyNames cho danh sách họ và UIFont.fontNames(forFamilyName:) cho tên PostScript. Gọi mã này ở chế độ gỡ lỗi và tìm phông chữ mong muốn. Tên PostScript thường chứa tên họ và kiểu: “SFProText-Regular”, “HelveticaNeue-Bold”.

UIFont có hỗ trợ phông chữ biến đổi không?

Có, qua UIFontDescriptor bạn có thể cấu hình trục biến đổi: weight, width, slant. Tuy nhiên, API UIFont cho phông chữ biến đổi bị giới hạn so với CTFontCopyVariation. Để kiểm soát đầy đủ trục biến đổi, sử dụng Core Text và CTFontCreateCopyWithVariation.

Làm thế nào để lưu đệm UIFont đúng cách?

Tạo một từ điển tĩnh hoặc NSCache với khóa kết hợp tên và kích thước. Cho phông chữ hệ thống, iOS tự động lưu đệm phiên bản, nhưng cho phông chữ tùy chỉnh tạo qua UIFont(name:size:), khuyến nghị lưu đối tượng trong bộ đệm ứng dụng để tránh tải lại từ tệp TTF.

Tóm tắt

  • UIFont — lớp UIKit cấp cao cho phông chữ trong thành phần UI với Dynamic Type
  • CTFont — kiểu Core Text cấp thấp để render và truy cập glyph
  • UIFont được tạo qua systemFont, preferredFont hoặc UIFont(name:size:)
  • CTFont được tạo qua CTFontCreateWithName hoặc CTFontCreateWithDescriptor
  • Toll-Free Bridging cho phép chuyển đổi miễn phí giữa UIFont và CTFont
  • Dynamic Type bắt buộc cho trợ năng: sử dụng preferredFont và adjustsFontForContentSizeCategory
  • Cho UIKit sử dụng UIFont, cho render tùy chỉnh sử dụng CTFont

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm