Font Descriptor คือวัตถุ UIFontDescriptor ใน iOS และ NSFontDescriptor ใน macOS ที่ห่อหุ้มข้อมูลเมตาทั้งหมดของแบบอักษร: ตระกูล ชนิด ขนาด ระยะห่างระหว่างตัวอักษร ระยะห่างระหว่างบรรทัด และคุณลักษณะการพิมพ์ แทนที่จะสร้างแบบอักษรโดยตรงผ่าน UIFont(name:size:) นักพัฒนาจะอธิบายคุณลักษณะที่ต้องการผ่านตัวบอกลักษณะ และระบบจะเลือกการจับคู่ที่ดีที่สุดจากแบบอักษรที่มีอยู่ ตาม เอกสารประกอบสำหรับนักพัฒนา Apple UIFontDescriptor รองรับคุณลักษณะแบบอักษรมากกว่า 20 รายการและถูกใช้ในเฟรมเวิร์กการพิมพ์ทั้งหมดของ iOS — ตั้งแต่ UIKit ไปจนถึง Core Text และ SwiftUI
ประเด็นสำคัญ
Font Descriptor คือวัตถุที่อธิบายคุณลักษณะของแบบอักษรเป็นชุดของคู่คีย์-ค่า แทนที่จะเป็นไฟล์แบบอักษรเฉพาะ แทนที่จะสร้างแบบอักษรตามชื่อ นักพัฒนาจะระบุตระกูล ชนิด ขนาด และคุณลักษณะเสริม และระบบจะเลือกการจับคู่ที่ดีที่สุด วิธีการนี้มีความสำคัญสำหรับการพิมพ์แบบปรับได้: ตัวบอกลักษณะเดียวกันสามารถทำงานบนเวอร์ชัน iOS ต่างกันซึ่งชุดแบบอักษรที่มีอยู่แตกต่างกัน ตามแนวทางการออกแบบส่วนติดต่อผู้ใช้ของ iOS การจับคู่แบบอักษรผ่านตัวบอกลักษณะเป็นวิธีที่แนะนำสำหรับการทำงานกับแบบอักษรไดนามิก
หากไม่มี Font Descriptor นักพัฒนาจะต้องตรวจสอบความพร้อมของแต่ละแบบอักษรตามชื่อและกำหนดตัวเลือกสำรองด้วยตนเอง ตัวบอกลักษณะจะทำให้กระบวนการนี้เป็นอัตโนมัติ: มันมีเมทริกซ์ความเข้ากันได้ของชนิด (ปกติ หนา เอียง หนาเอียง) และเมื่อไม่พบการจับคู่ที่แน่นอน มันจะส่งคืนชนิดที่ใกล้ที่สุดที่มีอยู่ การจับคู่ของระบบ ทำงานที่ระดับ Core Text และพร้อมใช้งานทั้งบน iOS และ macOS ผ่าน API NSFontDescriptor แบบครบวงจร
ตัวบอกลักษณะยังใช้สำหรับแบบอักษรที่กำหนดเอง — โหลดผ่าน Info.plist หรือเพิ่มด้วยตนเอง หากแบบอักษรถูกลงทะเบียนในระบบ ตัวบอกลักษณะของมันจะถูกสร้างขึ้นในลักษณะเดียวกับแบบอักษรของระบบ หมายเหตุข้ามแพลตฟอร์ม: แนวคิดของตัวบอกลักษณะมีอยู่ใน Android ผ่าน Typeface.Builder เช่นกัน แต่การใช้งาน iOS ผ่าน UIFontDescriptor ให้คุณลักษณะมากกว่าอย่างมีนัยสำคัญ — มากกว่า 20 รายการเทียบกับ 5 ใน Android
UIFontDescriptor มีคุณลักษณะที่จัดกลุ่มในพจนานุกรม fontAttributes ชนิด [UIFontDescriptor.AttributeName: Any] คุณลักษณะหลักประกอบด้วยตระกูลแบบอักษร ชื่อ ขนาด ลักษณะ (traits) เมทริกซ์การแปลง ขนาดเชิงแสง และรูปแบบข้อความ ตามเซสชัน 227 ของ WWDC 2019 ของ Apple การใช้รูปแบบข้อความ — Dynamic Type — เป็นข้อบังคับสำหรับแอปพลิเคชันที่รองรับการเข้าถึง
คุณลักษณะ traits คือพจนานุกรมที่มีลักษณะเชิงสัญลักษณ์: น้ำหนัก (UIFontWeightTrait) ความเอียง (UIFontSlantTrait) ความกว้าง (UIFontWidthTrait) และอื่นๆ ค่าเหล่านี้ถูกใช้โดยตัวจับคู่แบบอักษรเพื่อเลือกชนิด ตัวอย่างเช่น UIFontWeightTrait ที่มีค่า 0.0 — ชนิดปกติ 0.3 — หนา ระบบจะแมปค่าตัวเลขไปยังตัวแปรแบบอักษรที่มีอยู่โดยอัตโนมัติ
คุณลักษณะเพิ่มเติมรวมถึง featureSettings สำหรับคุณสมบัติ OpenType (การเชื่อมตัวอักษร การเว้นระยะ สัดส่วนตัวเลข) visibleName สำหรับแสดงต่อผู้ใช้ matrix สำหรับการแปลงแบบ affined ของแบบอักษร และ cascadeList สำหรับรายการแบบอักษรสำรองแบบเรียงซ้อน รายการคุณลักษณะทั้งหมดครอบคลุมสถานการณ์การพิมพ์เกือบทั้งหมดใน iOS และ macOS
| คุณลักษณะ | ชนิด | คำอธิบาย |
|---|---|---|
| UIFontDescriptorFamily | String | ตระกูลแบบอักษร (SF Pro, Helvetica Neue) |
| UIFontDescriptorName | String | ชื่อเต็มของแบบอักษร (HelveticaNeue-Bold) |
| UIFontDescriptorSize | NSNumber | ขนาดแบบอักษรเป็นพอยต์ |
| UIFontDescriptorMatrix | NSValue | เมทริกซ์การแปลงแบบ affined |
| UIFontDescriptorTraits | [String: Any] | ลักษณะเชิงสัญลักษณ์ของชนิด |
| UIFontDescriptorTextStyle | String | รูปแบบ Dynamic Type (headline, body, caption) |
วิธีหลักในการทำงานกับ Font Descriptor ใน iOS คือการสร้างตัวบอกลักษณะแล้วสร้าง UIFont จากมัน นี่เป็นวิธีที่ต้องการเมื่อคุณต้องการแบบอักษรที่มีคุณลักษณะเฉพาะโดยไม่ทราบชื่อที่แน่นอน กระบวนการประกอบด้วยสองขั้นตอน: การสร้าง UIFontDescriptor ผ่านตัวเริ่มต้นและการเรียกเมธอด font(withSize:) บนตัวบอกลักษณะ
import UIKit
// สร้างตัวบอกลักษณะแบบอักษรสำหรับตระกูล
let descriptor = UIFontDescriptor.init(
fontAttributes: [
.family: "SF Pro",
.traits: [
.weight: UIFont.Weight.bold
]
]
)
// สร้าง UIFont จากตัวบอกลักษณะ
let font = descriptor.font(withSize: 17)
วิธีการนี้รับประกันว่าระบบจะเลือกการจับคู่ที่ดีที่สุดสำหรับชนิดหนาของ SF Pro บนอุปกรณ์ปัจจุบัน ข้อได้เปรียบสำคัญ — โค้ดไม่ขึ้นอยู่กับเวอร์ชัน iOS: บน iOS 13 จะใช้ SF Pro; บนเวอร์ชันก่อนหน้านี้จะใช้ Helvetica Neue หรือแบบอักษรของระบบเริ่มต้น
ในการสร้างแบบอักษรที่มีขนาดไดนามิก ให้ใช้ตัวเริ่มต้นกับรูปแบบข้อความและมาตราส่วน Dynamic Type จะปรับขนาดโดยอัตโนมัติตามการตั้งค่าของผู้ใช้:
// ตัวบอกลักษณะ Dynamic Type
let bodyDescriptor = UIFontDescriptor
.preferredFontDescriptor(withTextStyle: .body)
// ทำให้แบบอักษรหนา
let boldDescriptor = bodyDescriptor.withSymbolicTraits([.traitBold])
// สร้าง UIFont โดยรักษาขนาดไดนามิก
let boldBodyFont = UIFont(
descriptor: boldDescriptor!,
size: bodyDescriptor.pointSize
)
สำคัญ: เมธอด withSymbolicTraits ส่งคืนตัวบอกลักษณะที่เป็นทางเลือก — หากชนิดที่ร้องขอไม่พร้อมใช้งาน จะส่งคืน nil ตรวจสอบตัวเลือกนี้ก่อนใช้งานเสมอ
Font Descriptor รองรับโมเดลที่ไม่สามารถเปลี่ยนแปลงได้ — แต่ละเมธอดการแก้ไขจะส่งคืนตัวบอกลักษณะใหม่พร้อมคุณลักษณะที่เปลี่ยนไป ซึ่งเป็นไปตาม ความหมายของค่า และทำให้โค้ดคาดการณ์ได้: ตัวบอกลักษณะเดิมไม่เคยเปลี่ยนแปลง เมธอดการแก้ไขหลักคือ: addingAttributes สำหรับเพิ่มคุณลักษณะ withFace สำหรับเปลี่ยนชนิด withSize สำหรับเปลี่ยนขนาด และ withMatrix สำหรับการแปลงแบบ affined
เมธอด addingAttributes มีความยืดหยุ่นมากที่สุด มันรับพจนานุกรมของคุณลักษณะและส่งคืนตัวบอกลักษณะใหม่ เมื่อคีย์ตรงกัน ค่าใหม่จะแทนที่ค่าเก่า ซึ่งช่วยให้รวมการเปลี่ยนแปลง: เพิ่มน้ำหนัก เปลี่ยนขนาด และเปิดใช้งานการเชื่อมตัวอักษรในการเรียกครั้งเดียว ตามคำถามทางเทคนิคของ Apple QA1682 addingAttributes เป็นวิธีที่แนะนำสำหรับการแก้ไขเป็นกลุ่มผ่านส่วนขยาย
กรณีการใช้งานจริง: การสร้างแบบอักษรสำหรับข้อความเว้นระยะคงที่ในโปรแกรมแก้ไขโค้ด นักพัฒนานำตัวบอกลักษณะเว้นระยะคงที่ของระบบ เพิ่มน้ำหนักที่ลดลงสำหรับเส้นบาง และเพิ่มระยะห่างระหว่างตัวอักษรผ่าน featureSettings ซึ่งให้โค้ดที่อ่านง่ายขึ้นโดยไม่ต้องโหลดแบบอักษรแยกต่างหาก
let monoDescriptor = UIFontDescriptor.monospacedDigitFontDescriptor()
// เพิ่มคุณลักษณะที่กำหนดเอง
let customDescriptor = monoDescriptor.addingAttributes([
.size: 14,
.traits: [
.weight: UIFont.Weight.medium
]
])
let monoFont = UIFont(
descriptor: customDescriptor,
size: 14
)
ข้อจำกัด: ไม่สามารถเปลี่ยนคุณลักษณะทั้งหมดได้หลังจากสร้างตัวบอกลักษณะแล้ว ตัวอย่างเช่น ตระกูลแบบอักษรถูกตั้งค่าครั้งเดียวระหว่างการเริ่มต้น หากคุณต้องการเปลี่ยนตระกูล ให้สร้างตัวบอกลักษณะใหม่ สิ่งนี้เกี่ยวข้องกับสถาปัตยกรรม Core Text ซึ่งตัวบอกลักษณะถูกผูกไว้กับทรัพยากรแบบอักษรเฉพาะ
การจับคู่แบบอักษร เป็นคุณสมบัติสำคัญของ Font Descriptor ที่เลือกการจับคู่ที่ดีที่สุดสำหรับคุณลักษณะที่ร้องขอจากแบบอักษรที่ติดตั้งโดยอัตโนมัติ กระบวนการประกอบด้วยสามขั้นตอน: การกรอง (การแยกแบบอักษรที่เข้ากันไม่ได้ออก) การจัดลำดับ (การเรียงลำดับตามระดับการจับคู่) และการเลือก (การส่งคืนผลลัพธ์ที่ดีที่สุด) การจับคู่จะดำเนินการที่ระดับ Core Text — เฟรมเวิร์กที่เป็นพื้นฐานของการพิมพ์ทั้งหมดของ iOS
ในการค้นหาแบบอักษรทั้งหมดที่ตรงกับตัวบอกลักษณะ ให้ใช้เมธอด matchingFontDescriptors มันส่งคืนอาร์เรย์ของตัวบอกลักษณะที่เรียงลำดับตามความเกี่ยวข้อง นักพัฒนาสามารถเลือกการจับคู่ที่แน่นอน (องค์ประกอบแรก) หรือวนซ้ำตัวเลือกสำหรับตรรกะที่กำหนดเอง ตามคู่มือการจัดการแบบอักษรของ Apple นี่เป็นวิธีเดียวที่จะได้รับรายการชนิดที่มีอยู่สำหรับตระกูลเฉพาะโดยไม่ต้องแจกแจงตามชื่อ
กรณีการใช้งาน: เมื่อเลือกแบบอักษรในอินเทอร์เฟซการตั้งค่าข้อความ ผู้ใช้เลือกตระกูล และแอปพลิเคชันใช้ matchingFontDescriptors เพื่อรับชนิดที่มีอยู่ทั้งหมดและแสดงในตัวเลือก หากไม่มีการจับคู่ นักพัฒนาจะต้องเขียนโค้ดรายการตัวเลือกที่เปลี่ยนแปลงระหว่างเวอร์ชัน iOS แบบตายตัว
let searchDescriptor = UIFontDescriptor.init(
fontAttributes: [.family: "SF Mono"]
)
// รับชนิดที่มีอยู่ทั้งหมด
let matchingDescriptors = searchDescriptor
.matchingFontDescriptors(withMandatoryKeys: nil)
for descriptor in matchingDescriptors {
print(descriptor.object(forKey: .visibleName) ?? "unnamed")
}
คีย์บังคับ — พารามิเตอร์ที่จำกัดการค้นหา หากคุณระบุ [.family] การจับคู่จะส่งคืนแบบอักษรทั้งหมดของตระกูลที่ระบุ หากคุณระบุ [.family, .traits] — เฉพาะที่ตรงกับทั้งตระกูลและชนิด การใช้คีย์บังคับจะเร่งการจับคู่เมื่อค้นหาชุดย่อยของแบบอักษร
ประสิทธิภาพ: การจับคู่เป็นการดำเนินการแบบซิงโครนัสที่ใช้เวลา 0.5 ถึง 5 มิลลิวินาทีบน iOS สำหรับการค้นหาเดี่ยว สิ่งนี้ไม่สำคัญ แต่สำหรับการวนซ้ำเป็นกลุ่มบนตัวบอกลักษณะ (เช่น ในตัวเลือกที่มีแบบอักษรมากกว่า 50 รายการ) แนะนำให้เก็บผลลัพธ์ไว้ในแคช Apple แนะนำให้ดำเนินการจับคู่ครั้งเดียวเมื่อโหลดหน้าจอและบันทึกอาร์เรย์ของตัวบอกลักษณะ
Core Text เป็นเฟรมเวิร์กระดับต่ำที่ใช้ C สำหรับทำงานกับการพิมพ์บน iOS และ macOS สิ่งที่เทียบเท่ากับ UIFontDescriptor คือ CTFontDescriptor ซึ่งให้ความสามารถเดียวกันที่ระดับ Core Foundation CTFontDescriptor ถูกใช้ใน API ของ Core Text สำหรับการสร้างแบบอักษร การวัดข้อความ และการเรนเดอร์การพิมพ์ที่ซับซ้อน UIFontDescriptor โดยพื้นฐานแล้วเป็น wrapper Objective-C รอบ CTFontDescriptor พร้อมชุดคุณลักษณะที่ขยายเพิ่ม
การเชื่อมต่อแบบ toll-free ระหว่าง UIFontDescriptor และ CTFontDescriptor อนุญาตให้ส่งตัวบอกลักษณะระหว่าง UIKit และ Core Text โดยไม่ต้องแปลง ซึ่งมีความสำคัญสำหรับแอปพลิเคชันที่ใช้การเรนเดอร์ข้อความที่กำหนดเอง — ตัวอย่างเช่น โปรแกรมแก้ไขข้อความที่ใช้ TextKit หรือโปรแกรมแก้ไขโค้ดที่มีการเน้นไวยากรณ์ ตัวอย่าง: CTFontDescriptorCreateCopyWithAttribute สร้างสำเนาของตัวบอกลักษณะที่มีคุณลักษณะเพิ่ม — คล้ายกับ addingAttributes ของ UIFontDescriptor
คุณลักษณะสำคัญ kCTFontURLAttribute ใน CTFontDescriptor มี URL ของไฟล์แบบอักษร ซึ่งช่วยให้ระบุได้ว่าแบบอักษรเป็นของระบบหรือกำหนดเอง สำหรับแบบอักษรที่กำหนดเอง URL จะชี้ไปที่ไฟล์แบบอักษร (.ttf หรือ .otf); สำหรับแบบอักษรของระบบ จะชี้ไปที่ไดเรกทอรีแบบอักษรของระบบ ข้อมูลผ่านตัวบอกลักษณะเป็นแบบอ่านอย่างเดียว; การแก้ไขไฟล์แบบอักษรผ่าน URL ไม่ได้รับการสนับสนุน
สำหรับการพิมพ์ขั้นสูง — การเชื่อมตัวอักษรที่กำหนดเอง การแทนที่ตามบริบท กลิฟทางเลือก — ให้ใช้ CTFontDescriptorCopyAttribute กับคีย์ kCTFontFeatureSettingsAttribute คุณลักษณะนี้มีอาร์เรย์ของพจนานุกรมคุณสมบัติ OpenType ที่สามารถเพิ่มผ่านตัวบอกลักษณะ ตามคู่มือการเขียนโปรแกรม Core Text ของ Apple การรวม UIFontDescriptor กับ Core Text ให้การควบคุมการพิมพ์ของแอปพลิเคชันอย่างสมบูรณ์
คำถามที่พบบ่อย
UIFont คือแบบอักษรที่พร้อมใช้งานซึ่งเรนเดอร์ข้อความ Font Descriptor คือคำอธิบายแบบอักษร — ชุดคุณลักษณะที่สามารถสร้าง UIFont ได้ ตัวบอกลักษณะหนึ่งตัวสามารถสร้าง UIFont หลายขนาดที่แตกต่างกันได้
ได้ หากแบบอักษรถูกลงทะเบียนในระบบ (ผ่าน Info.plist หรือ Core Graphics) ตัวบอกลักษณะของมันจะถูกสร้างขึ้นตาม ตระกูล หรือตาม ชื่อ เช่นเดียวกับแบบอักษรของระบบ การจับคู่ทำงานสำหรับแบบอักษรที่ลงทะเบียนทั้งหมด
ใช้ descriptor.object(forKey: .visibleName) เพื่อรับชื่อที่แสดง หรือ descriptor.postscriptName สำหรับชื่อ PostScript ชื่อ PostScript ใช้เมื่อสร้างแบบอักษรผ่าน UIFont(name:size:)
รายการเรียงซ้อน คืออาร์เรย์ของตัวบอกลักษณะที่ซ้อนกันซึ่งทำหน้าที่เป็นแบบอักษรสำรอง หากแบบอักษรหลักไม่มีอักขระที่ต้องการ ระบบจะตรวจสอบแบบอักษรจากรายการเรียงซ้อนตามลำดับ ใช้สำหรับการรองรับอิโมจิและอักขระ CJK
ได้ SwiftUI รองรับ Font Descriptor ผ่าน Font(descriptor:size:) wrapper ของ SwiftUI รับ UIFontDescriptor และสร้างแบบอักษร SwiftUI โดยรักษาคุณลักษณะทั้งหมดของตัวบอกลักษณะ — การเว้นระยะ การเชื่อมตัวอักษร และชนิด
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ