Font Descriptor: các khái niệm chính và khả năng của bộ mô tả phông chữ

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

Font Descriptor là đối tượng UIFontDescriptor trong iOS và NSFontDescriptor trong macOS, đóng gói tất cả siêu dữ liệu phông chữ: họ, kiểu chữ, kích thước, khoảng cách chữ, khoảng cách dòng và các thuộc tính kiểu chữ. Thay vì tạo phông chữ trực tiếp qua UIFont(name:size:), nhà phát triển mô tả các đặc tính mong muốn thông qua bộ mô tả và hệ thống chọn kết quả phù hợp nhất từ các phông chữ có sẵn. Theo Tài liệu Nhà phát triển Apple, UIFontDescriptor hỗ trợ hơn 20 thuộc tính phông chữ và được sử dụng trong tất cả các framework kiểu chữ iOS — từ UIKit đến Core Text và SwiftUI.

Những điểm chính

  • Font Descriptor — đối tượng mô tả chứa siêu dữ liệu về họ, kiểu chữ, kích thước và thuộc tính kiểu chữ
  • Cho phép tạo UIFont từ một tập hợp các thuộc tính mà không cần chỉ định tên phông chữ cụ thể
  • Hỗ trợ sửa đổi phông chữ hiện có: thay đổi kích thước, kiểu chữ và kerning mà không tạo đối tượng mới
  • Được sử dụng trong UIKit, Core Text và SwiftUI để tra cứu và cấu hình phông chữ
  • Cung cấp so khớp phông chữ — tự động chọn kiểu chữ có sẵn gần nhất

Font Descriptor là gì và tại sao cần nó

Font Descriptor là một đối tượng mô tả đặc tính phông chữ dưới dạng tập hợp các cặp khóa-giá trị, thay vì một tệp phông chữ cụ thể. Thay vì tạo phông chữ theo tên, nhà phát triển chỉ định họ, kiểu chữ, kích thước và các thuộc tính tùy chọn, và hệ thống chọn kết quả phù hợp nhất. Cách tiếp cận này rất quan trọng cho kiểu chữ thích ứng: cùng một bộ mô tả có thể hoạt động trên các phiên bản iOS khác nhau, nơi tập hợp phông chữ có sẵn khác nhau. Theo Hướng dẫn Giao diện Người dùng iOS, so khớp phông chữ qua bộ mô tả là cách được khuyến nghị để làm việc với phông chữ động.

Không có Font Descriptor, các nhà phát triển sẽ phải kiểm tra tính khả dụng của từng phông chữ theo tên và tự động xác định các tùy chọn dự phòng. Bộ mô tả tự động hóa quy trình này: nó chứa ma trận tương thích của các kiểu chữ (thường, đậm, nghiêng, đậm nghiêng) và khi không tìm thấy kết quả khớp chính xác, nó trả về kết quả gần nhất có sẵn. So khớp hệ thống hoạt động ở cấp Core Text và có sẵn trên cả iOS và macOS thông qua API NSFontDescriptor thống nhất.

Các bộ mô tả cũng được sử dụng cho phông chữ tùy chỉnh — được tải qua Info.plist hoặc thêm thủ công. Nếu một phông chữ được đăng ký trong hệ thống, bộ mô tả của nó được tạo giống hệt như cho phông chữ hệ thống. Lưu ý đa nền tảng: khái niệm bộ mô tả cũng tồn tại trong Android qua Typeface.Builder, nhưng triển khai iOS qua UIFontDescriptor cung cấp nhiều thuộc tính hơn đáng kể — hơn 20 so với 5 trong Android.

Các thuộc tính chính của Font Descriptor

UIFontDescriptor chứa các thuộc tính được nhóm trong từ điển fontAttributes kiểu [UIFontDescriptor.AttributeName: Any]. Các thuộc tính chính bao gồm họ phông chữ, tên, kích thước, đặc điểm (traits), ma trận biến đổi, kích thước quang học và kiểu văn bản. Theo Phiên 227 của WWDC 2019 của Apple, việc sử dụng kiểu văn bản — Dynamic Type — là bắt buộc đối với các ứng dụng tương thích trợ năng.

Thuộc tính traits là một từ điển chứa các đặc điểm ký hiệu: trọng lượng (UIFontWeightTrait), độ nghiêng (UIFontSlantTrait), độ rộng (UIFontWidthTrait) và các đặc điểm khác. Các giá trị này được bộ so khớp phông chữ sử dụng để chọn kiểu chữ. Ví dụ: UIFontWeightTrait với giá trị 0.0 — kiểu chữ thường, 0.3 — đậm. Hệ thống tự động ánh xạ các giá trị số sang các biến thể phông chữ có sẵn.

Các thuộc tính bổ sung bao gồm featureSettings cho các tính năng OpenType (ligatures, kerning, tỷ lệ số), visibleName để hiển thị cho người dùng, matrix cho các biến đổi affine của phông chữ và cascadeList cho danh sách phông chữ dự phòng xếp tầng. Danh sách đầy đủ các thuộc tính bao phủ hầu như tất cả các tình huống kiểu chữ trong iOS và macOS.

Thuộc tínhLoạiMô tả
UIFontDescriptorFamilyStringHọ phông chữ (SF Pro, Helvetica Neue)
UIFontDescriptorNameStringTên đầy đủ của phông chữ (HelveticaNeue-Bold)
UIFontDescriptorSizeNSNumberKích thước phông chữ tính bằng điểm
UIFontDescriptorMatrixNSValueMa trận biến đổi affine
UIFontDescriptorTraits[String: Any]Đặc điểm ký hiệu của kiểu chữ
UIFontDescriptorTextStyleStringKiểu Dynamic Type (headline, body, caption)

Tạo UIFont qua Font Descriptor trong Swift

Cách chính để làm việc với Font Descriptor trong iOS là tạo một bộ mô tả và sau đó tạo UIFont từ nó. Đây là cách tiếp cận được ưa thích khi bạn cần một phông chữ với các đặc tính cụ thể mà không biết tên chính xác. Quy trình gồm hai bước: tạo UIFontDescriptor qua bộ khởi tạo và gọi phương thức font(withSize:) trên bộ mô tả.

swift
import UIKit

// Tạo bộ mô tả phông chữ cho họ
let descriptor = UIFontDescriptor.init(
    fontAttributes: [
        .family: "SF Pro",
        .traits: [
            .weight: UIFont.Weight.bold
        ]
    ]
)

// Tạo UIFont từ bộ mô tả
let font = descriptor.font(withSize: 17)

Cách tiếp cận này đảm bảo hệ thống chọn kết quả phù hợp nhất cho kiểu chữ đậm của SF Pro trên thiết bị hiện tại. Lợi thế chính — mã không phụ thuộc vào phiên bản iOS: trên iOS 13, SF Pro sẽ được sử dụng; trên các phiên bản cũ hơn, Helvetica Neue hoặc phông chữ hệ thống mặc định.

Để tạo phông chữ với kích thước động, hãy sử dụng bộ khởi tạo với kiểu văn bản và tỷ lệ. Dynamic Type tự động điều chỉnh kích thước theo cài đặt của người dùng:

swift
// Bộ mô tả Dynamic Type
let bodyDescriptor = UIFontDescriptor
    .preferredFontDescriptor(withTextStyle: .body)

// Làm đậm phông chữ
let boldDescriptor = bodyDescriptor.withSymbolicTraits([.traitBold])

// Tạo UIFont giữ nguyên kích thước động
let boldBodyFont = UIFont(
    descriptor: boldDescriptor!,
    size: bodyDescriptor.pointSize
)

Quan trọng: phương thức withSymbolicTraits trả về một bộ mô tả tùy chọn — nếu kiểu chữ được yêu cầu không khả dụng, nó trả về nil. Luôn kiểm tra tùy chọn trước khi sử dụng.

Sửa đổi thuộc tính bằng cách thêm và thay thế

Font Descriptor hỗ trợ mô hình bất biến — mỗi phương thức sửa đổi trả về một bộ mô tả mới với thuộc tính đã thay đổi. Điều này tuân theo ngữ nghĩa giá trị và làm cho mã có thể dự đoán được: bộ mô tả gốc không bao giờ thay đổi. Các phương thức sửa đổi chính là: addingAttributes để thêm thuộc tính, withFace để thay đổi kiểu chữ, withSize để thay đổi kích thước và withMatrix cho biến đổi affine.

Phương thức addingAttributes là linh hoạt nhất. Nó nhận một từ điển các thuộc tính và trả về một bộ mô tả mới. Khi các khóa trùng khớp, các giá trị mới thay thế các giá trị cũ. Điều này cho phép kết hợp các thay đổi: thêm trọng lượng, thay đổi kích thước và bật ligatures trong một lần gọi. Theo Câu hỏi Kỹ thuật Apple QA1682, addingAttributes là cách được khuyến nghị để sửa đổi hàng loạt qua tiện ích mở rộng.

Trường hợp sử dụng thực tế: tạo phông chữ cho văn bản đơn cách trong trình soạn thảo mã. Nhà phát triển lấy bộ mô tả đơn cách của hệ thống, thêm trọng lượng giảm cho các đường mảnh và tăng khoảng cách chữ qua featureSettings. Điều này cung cấp mã dễ đọc hơn mà không cần tải một phông chữ riêng biệt.

swift
let monoDescriptor = UIFontDescriptor.monospacedDigitFontDescriptor()

// Thêm thuộc tính tùy chỉnh
let customDescriptor = monoDescriptor.addingAttributes([
    .size: 14,
    .traits: [
        .weight: UIFont.Weight.medium
    ]
])

let monoFont = UIFont(
    descriptor: customDescriptor,
    size: 14
)

Giới hạn: không phải tất cả các thuộc tính đều có thể thay đổi sau khi tạo bộ mô tả. Ví dụ, họ phông chữ được đặt một lần trong quá trình khởi tạo. Nếu bạn cần thay đổi họ, hãy tạo một bộ mô tả mới. Điều này liên quan đến kiến trúc Core Text, nơi bộ mô tả được gắn với một tài nguyên phông chữ cụ thể.

So khớp phông chữ và tìm kiếm phông chữ hệ thống

So khớp phông chữ là một tính năng chính của Font Descriptor tự động chọn kết quả phù hợp nhất cho các thuộc tính được yêu cầu trong số các phông chữ đã cài đặt. Quy trình bao gồm ba giai đoạn: lọc (loại trừ các phông chữ không tương thích), xếp hạng (sắp xếp theo mức độ phù hợp) và chọn lọc (trả về kết quả tốt nhất). Việc so khớp được thực hiện ở cấp Core Text — framework nền tảng của tất cả kiểu chữ iOS.

Để tìm tất cả các phông chữ khớp với một bộ mô tả, hãy sử dụng phương thức matchingFontDescriptors. Nó trả về một mảng các bộ mô tả được sắp xếp theo mức độ liên quan. Nhà phát triển có thể chọn kết quả khớp chính xác (phần tử đầu tiên) hoặc duyệt qua các tùy chọn cho logic tùy chỉnh. Theo Hướng dẫn Xử lý Phông chữ Apple, đây là cách duy nhất để có được danh sách các kiểu chữ có sẵn cho một họ cụ thể mà không cần liệt kê theo tên.

Trường hợp sử dụng: khi chọn phông chữ trong giao diện cài đặt văn bản. Người dùng chọn một họ và ứng dụng sử dụng matchingFontDescriptors để lấy tất cả các kiểu chữ có sẵn và hiển thị chúng trong bộ chọn. Nếu không có so khớp, các nhà phát triển sẽ phải mã cứng một danh sách các tùy chọn thay đổi giữa các phiên bản iOS.

swift
let searchDescriptor = UIFontDescriptor.init(
    fontAttributes: [.family: "SF Mono"]
)

// Lấy tất cả các kiểu chữ có sẵn
let matchingDescriptors = searchDescriptor
    .matchingFontDescriptors(withMandatoryKeys: nil)

for descriptor in matchingDescriptors {
    print(descriptor.object(forKey: .visibleName) ?? "unnamed")
}

Khóa bắt buộc — tham số giới hạn tìm kiếm. Nếu bạn chỉ định [.family], so khớp trả về tất cả phông chữ của họ được chỉ định. Nếu bạn chỉ định [.family, .traits] — chỉ những phông chữ khớp cả họ và kiểu chữ. Sử dụng khóa bắt buộc tăng tốc so khớp khi tìm kiếm một tập hợp con phông chữ.

Hiệu suất: so khớp là một thao tác đồng bộ mất 0,5 đến 5 ms trên iOS. Đối với một tìm kiếm đơn lẻ, điều này không đáng kể, nhưng đối với việc lặp lại hàng loạt trên các bộ mô tả (ví dụ: trong bộ chọn với hơn 50 phông chữ), nên lưu vào bộ nhớ đệm kết quả. Apple khuyến nghị thực hiện so khớp một lần khi tải màn hình và lưu mảng các bộ mô tả.

Tích hợp với Core Text và CTFontDescriptor

Core Text là một framework cấp thấp dựa trên C để làm việc với kiểu chữ trên iOS và macOS. Đối tác của UIFontDescriptor là CTFontDescriptor, cung cấp các khả năng tương tự ở cấp Core Foundation. CTFontDescriptor được sử dụng trong các API Core Text để tạo phông chữ, đo văn bản và kết xuất kiểu chữ phức tạp. UIFontDescriptor về cơ bản là một wrapper Objective-C xung quanh CTFontDescriptor với một tập hợp thuộc tính mở rộng.

Cầu nối toll-free giữa UIFontDescriptor và CTFontDescriptor cho phép truyền các bộ mô tả giữa UIKit và Core Text mà không cần chuyển đổi. Điều này rất quan trọng đối với các ứng dụng sử dụng kết xuất văn bản tùy chỉnh — ví dụ: trình soạn thảo văn bản dựa trên TextKit hoặc trình soạn thảo mã với tô sáng cú pháp. Ví dụ: CTFontDescriptorCreateCopyWithAttribute tạo một bản sao của bộ mô tả với một thuộc tính được thêm vào — tương tự như addingAttributes của UIFontDescriptor.

Thuộc tính chính kCTFontURLAttribute trong CTFontDescriptor chứa URL của tệp phông chữ. Điều này cho phép xác định phông chữ là hệ thống hay tùy chỉnh. Đối với phông chữ tùy chỉnh, URL trỏ đến tệp phông chữ (.ttf hoặc .otf); đối với phông chữ hệ thống, nó trỏ đến thư mục phông chữ hệ thống. Dữ liệu qua bộ mô tả là chỉ đọc; việc sửa đổi tệp phông chữ qua URL không được hỗ trợ.

Đối với kiểu chữ nâng cao — ligatures tùy chỉnh, thay thế ngữ cảnh, glyph thay thế — hãy sử dụng CTFontDescriptorCopyAttribute với khóa kCTFontFeatureSettingsAttribute. Thuộc tính này chứa một mảng các từ điển tính năng OpenType có thể được thêm qua bộ mô tả. Theo Hướng dẫn Lập trình Core Text của Apple, kết hợp UIFontDescriptor với Core Text mang lại toàn quyền kiểm soát kiểu chữ của ứng dụng.

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

Font Descriptor khác UIFont như thế nào?

UIFont là một phông chữ sẵn sàng sử dụng để kết xuất văn bản. Font Descriptor là một mô tả phông chữ — một tập hợp các thuộc tính mà từ đó có thể tạo UIFont. Một bộ mô tả có thể tạo ra nhiều UIFont với các kích thước khác nhau.

Có thể sử dụng Font Descriptor cho phông chữ tùy chỉnh không?

Có. Nếu phông chữ được đăng ký trong hệ thống (qua Info.plist hoặc Core Graphics), bộ mô tả của nó được tạo theo họ hoặc theo tên giống hệt như cho phông chữ hệ thống. So khớp hoạt động cho bất kỳ phông chữ đã đăng ký nào.

Làm thế nào để lấy tên phông chữ từ bộ mô tả?

Sử dụng descriptor.object(forKey: .visibleName) để lấy tên hiển thị, hoặc descriptor.postscriptName để lấy tên PostScript. Tên PostScript được sử dụng khi tạo phông chữ qua UIFont(name:size:).

Danh sách xếp tầng trong Font Descriptor là gì?

Danh sách xếp tầng là một mảng các bộ mô tả lồng nhau đóng vai trò là phông chữ dự phòng. Nếu phông chữ chính không chứa ký tự cần thiết, hệ thống sẽ kiểm tra tuần tự các phông chữ từ danh sách xếp tầng. Nó được sử dụng để hỗ trợ biểu tượng cảm xúc và ký tự CJK.

Font Descriptor có hoạt động trong SwiftUI không?

Có. SwiftUI hỗ trợ Font Descriptor qua Font(descriptor:size:). Wrapper SwiftUI chấp nhận UIFontDescriptor và tạo phông chữ SwiftUI, bảo toàn tất cả các thuộc tính của bộ mô tả — kerning, ligatures và kiểu chữ.

Tổng kết

  • Font Descriptor — đối tượng mô tả với các thuộc tính về họ, kiểu chữ, kích thước và tính năng kiểu chữ
  • Cho phép tạo UIFont từ một tập hợp các thuộc tính với so khớp phông chữ tự động
  • Hỗ trợ sửa đổi bất biến qua addingAttributes, withSize, withSymbolicTraits
  • matchingFontDescriptors trả về tất cả các kiểu chữ có sẵn để tìm kiếm và chọn phông chữ
  • Tích hợp với Core Text qua cầu nối toll-free giữa UIFontDescriptor và CTFontDescriptor
  • Hỗ trợ Dynamic Type qua các kiểu văn bản ưa thích và chia tỷ lệ
  • Được khuyến nghị cho kiểu chữ thích ứng hỗ trợ tất cả các phiên bản iOS mà không cần kiểm tra tính khả dụng của phông chữ

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