UIFont และ CTFont เป็นคลาสสำหรับทำงานกับฟอนต์ใน iOS: UIFont จาก UIKit สำหรับการกำหนดค่าข้อความระดับสูงใน UILabel และ UITextView, CTFont จาก Core Text สำหรับการเรนเดอร์ระดับต่ำที่ควบคุมกลิฟและเมตริกได้อย่างสมบูรณ์ ตาม Apple Developer Documentation พบว่า UIFont ถูกใช้ใน 90% ของคอมโพเนนต์ UI มาตรฐาน ในขณะที่ CTFont ถูกใช้ในเอนจินข้อความและตัวแก้ไขแบบกำหนดเอง ทั้งสองคลาสแทนฟอนต์เดียวกันแต่มีระดับนามธรรมที่แตกต่างกัน
ประเด็นสำคัญ
UIFont เป็นคลาส UIKit ที่แทนฟอนต์สำหรับแสดงข้อความในคอมโพเนนต์ UI: UILabel, UITextView, UITextField โดยให้อินเทอร์เฟซที่เรียบง่ายสำหรับการรับฟอนต์ระบบและฟอนต์กำหนดเองพร้อมขนาด น้ำหนัก และสไตล์ที่ระบุ UIFont ไม่อนุญาตให้ควบคุมการปรับระยะห่าง ลิเกเจอร์ และคุณสมบัติ OpenType โดยตรง — ใช้ Core Text สำหรับสิ่งนั้น
CTFont เป็นประเภท Core Text (CTFontRef) ที่ให้การเข้าถึงข้อมูลฟอนต์ระดับต่ำ CTFont ทำงานโดยตรงกับ Core Graphics สำหรับการเรนเดอร์ รองรับคุณสมบัติ OpenType และ TrueType ทั้งหมด รวมถึงกลิฟทางเลือก ลิเกเจอร์ และฟอนต์แปรผัน CTFont ถูกใช้ภายในโดย UIKit สำหรับการเรนเดอร์ UIFont แต่ยังพร้อมใช้งานโดยตรงสำหรับการวาดแบบกำหนดเอง
UIFont และ CTFont รองรับ Toll-Free Bridging — การแปลงระหว่างประเภทโดยไม่มีค่าใช้จ่ายเพิ่มเติม การแคสต์ UIFont as CTFont หรือ CTFont as UIFont เป็นไปได้ใน Swift และ Objective-C ซึ่งช่วยให้ใช้ API ระดับสูงของ UIKit สำหรับการกำหนดค่าและ Core Text ระดับต่ำสำหรับการเรนเดอร์โดยไม่ต้องคัดลอกข้อมูลฟอนต์
ทั้งสองคลาสใช้ UIFontDescriptor (UIKit) / CTFontDescriptor (Core Text) เพื่ออธิบายคุณลักษณะของฟอนต์: ชื่อ ขนาด น้ำหนัก สไตล์ เมทริกซ์การแปลง ตัวบอกลักษณะคือพจนานุกรมของคุณสมบัติที่สามารถแก้ไขเพื่อสร้างฟอนต์ใหม่จากฟอนต์ที่มีอยู่ ตัวอย่างเช่น เพิ่ม traitItalic ลงในตัวบอกลักษณะและรับรุ่นเอียงของฟอนต์เดียวกัน
UIFont มีเมธอดโรงงานหลายแบบสำหรับสร้างฟอนต์ systemFont(ofSize:) คืนค่าฟอนต์ระบบ San Francisco (iOS) หรือ Helvetica (รุ่นเก่า) boldSystemFont, italicSystemFont — รูปแบบที่มีสไตล์เฉพาะ preferredFont(forTextStyle:) คืนค่าฟอนต์ Dynamic Type สำหรับสไตล์ที่กำหนด: .headline, .body, .caption1, .footnote ฟอนต์เหล่านี้ปรับขนาดโดยอัตโนมัติเมื่อการตั้งค่าขนาดข้อความในระบบเปลี่ยนแปลง
สำหรับการโหลดฟอนต์กำหนดเอง ใช้ UIFont(name:size:) กับชื่อ PostScript ของฟอนต์ ฟอนต์ต้องถูกเพิ่มไปยัง Info.plist ก่อนและรวมอยู่ในบันเดิลแอป ตามข้อมูลของ Apple แนะนำให้ใช้ UIFont สำหรับคอมโพเนนต์ UI มาตรฐานทั้งหมดและเปลี่ยนไปใช้ CTFont เฉพาะเมื่อต้องการการเรนเดอร์แบบกำหนดเอง
Dynamic Type เป็นระบบฟอนต์ปรับตัวที่เปิดตัวใน iOS 7 ผู้ใช้เลือกขนาดข้อความที่ต้องการในการตั้งค่า — จากเล็กพิเศษไปจนถึงใหญ่พิเศษ UIFont.preferredFont คืนค่าฟอนต์ที่มีขนาดเหมาะสมโดยอัตโนมัติ สำหรับการทำงานที่ถูกต้อง UILabel ทั้งหมดควรมี adjustsFontForContentSizeCategory = true Dynamic Type จำเป็นสำหรับการปฏิบัติตามข้อกำหนดการช่วยเหลือ
UIFontDescriptor ช่วยให้แก้ไขคุณลักษณะฟอนต์โดยไม่ต้องสร้างอินสแตนซ์ใหม่จากเริ่มต้น เมธอด addingAttributes(_:), withSymbolicTraits(_:), withFamily(_:) คืนค่าตัวบอกลักษณะใหม่พร้อมพารามิเตอร์ที่เปลี่ยนแปลง ซึ่งสะดวกสำหรับการรับรุ่นของฟอนต์: เพิ่ม traitBold ลงในฟอนต์ระบบและรับรุ่นตัวหนาโดยไม่ต้องรู้ชื่อ PostScript
CTFont (CTFontRef) เป็นประเภท Core Text สำหรับการทำงานกับฟอนต์ระดับต่ำ มันถูกสร้างโดย CTFontCreateWithName, CTFontCreateWithFontDescriptor, CTFontCreateCopyWithAttributes แต่ละฟังก์ชันคืนค่าฟอนต์พร้อมอินเทอร์เฟซ ขนาด และคุณสมบัติเสริมที่ระบุ CTFont ใช้ใน Core Graphics สำหรับการเรนเดอร์ข้อความบน UIView แบบกำหนดเองผ่าน drawRect
CTFont ให้การเข้าถึงเมตริกที่ไม่พร้อมใช้งานใน UIFont: CTFontGetGlyphsForCharacters คืนค่าอาร์เรย์ของกลิฟสำหรับอักขระที่กำหนด CTFontGetAdvancesForGlyphs — ความกว้างของแต่ละกลิฟ CTFontGetBoundingBox — ขอบเขตของกลิฟ ซึ่งจำเป็นสำหรับการสร้างเค้าโครงข้อความแบบกำหนดเอง: คอลัมน์ การหมุน การตัดคำ
CTFontGetAscent, CTFontGetDescent, CTFontGetLeading คืนค่าเมตริกแนวตั้งของฟอนต์ CTFontGetUnitsPerEm — จำนวนหน่วยต่อตาราง em ใช้สำหรับคำนวณสัดส่วน CTFontGetGlyphCount — จำนวนกลิฟทั้งหมดในฟอนต์ ข้อมูลนี้สำคัญสำหรับการพิมพ์แบบเรียงพิมพ์และเค้าโครงกำหนดเองที่ต้องการการวางตำแหน่งที่แม่นยำของแต่ละอักขระ
CTFont รองรับคุณสมบัติ OpenType: CTFontCopyFeatures คืนค่าพจนานุกรมของฟังก์ชันฟอนต์ที่พร้อมใช้งาน (ลิเกเจอร์ อักขระทางเลือก การปรับระยะห่าง) CTFontEnableFeature เปิดใช้งานตัวเลือกเฉพาะ ฟอนต์แปรผันถูกกำหนดค่าผ่าน CTFontCopyVariation และ CTFontCreateCopyWithVariation ซึ่งอนุญาตให้เปลี่ยน weight, width และ slant ในช่วงต่อเนื่อง
การสร้าง 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 โดยอัตโนมัติ
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:) จากทุกที่ในแอป
// รับชื่อตระกูลฟอนต์ทั้งหมด
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:) ระหว่างการดีบักเพื่อให้แน่ใจว่าฟอนต์ถูกลงทะเบียนอย่างถูกต้อง
การโหลดฟอนต์กำหนดเองทำได้สองวิธี: การลงทะเบียนแบบคงที่ผ่าน Info.plist (UIAppFonts) และการลงทะเบียนแบบไดนามิกผ่าน CTFontManagerRegisterGraphicsFont วิธีแรกง่ายกว่า — ฟอนต์พร้อมใช้งานทันทีหลังจากเปิดแอป วิธีที่สองใช้สำหรับฟอนต์ที่ดาวน์โหลดจากเครือข่ายหรือทรัพยากรตามความต้องการ
การลงทะเบียนแบบไดนามิกมีประโยชน์สำหรับ ทรัพยากรตามความต้องการ: หากแอปมีฟอนต์มากกว่า 20 ฟอนต์ สามารถแยกทั้งหมดออกจากบันเดิลเริ่มต้นและดาวน์โหลดเมื่อใช้งานครั้งแรก CTFontManagerRegisterFontsForURLs ลงทะเบียนฟอนต์จาก URL ที่ระบุ หลังจากการลงทะเบียน ฟอนต์พร้อมใช้งานผ่าน UIFont(name:size:) ตามปกติ
สำหรับการเรนเดอร์แบบกำหนดเองผ่าน Core Text ใช้ CTFontCreateWithName กับชื่อ PostScript ของฟอนต์ ความแตกต่างกับ UIFont คือ CTFont สามารถสร้างด้วยเมทริกซ์การแปลง (CTFontCreateWithNameAndOptions) — สำหรับสร้างฟอนต์ที่บิดเบี้ยว: การเอียง การปรับสเกลแกน X การหมุน ซึ่งไม่พร้อมใช้งานใน UIFont โดยไม่ใช้การแปลงแบบแอฟฟีน
// สร้าง 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
เมทริกซ์การแปลงช่วยให้สร้างรุ่น เอียง โดยไม่ต้องมีไฟล์ฟอนต์แยกต่างหาก พารามิเตอร์ c (skew) เพิ่มความเอียงให้กับอักขระ เมทริกซ์ยังอนุญาตให้ปรับสเกลฟอนต์ในแนวนอน — สร้างรุ่นที่ condensed หรือ expanded ของฟอนต์เดียว
ความแตกต่างหลักระหว่าง UIFont และ CTFont คือระดับนามธรรม UIFont ให้ API ที่เรียบง่ายสำหรับงานทั่วไป: รับฟอนต์ระบบ เปลี่ยนขนาด ใช้กับ UILabel CTFont ให้การควบคุมฟอนต์อย่างสมบูรณ์: การเข้าถึงกลิฟ เมตริก ตาราง OpenType และแกนแปรผัน การเลือกขึ้นอยู่กับงาน
| คุณลักษณะ | UIFont | CTFont |
|---|---|---|
| เฟรมเวิร์ก | UIKit | Core Text |
| การสร้าง | systemFont / preferredFont / initWithName | CTFontCreateWithName / CTFontCreateWithDescriptor |
| การเข้าถึงกลิฟ | ไม่ | CTFontGetGlyphsForCharacters |
| คุณสมบัติ OpenType | จำกัด (UIFontDescriptor) | เข้าถึงได้ทั้งหมด |
| ฟอนต์แปรผัน | ผ่าน UIFontDescriptor | CTFontCopyVariation / CreateCopyWithVariation |
| การเรนเดอร์ | อัตโนมัติในคอมโพเนนต์ UI | Core Graphics, กำหนดเอง |
สำหรับ 95% ของงานพัฒนา iOS UIFont ก็เพียงพอ Core Text กับ CTFont เหมาะสมเมื่อสร้างตัวแก้ไขข้อความ เครื่องสร้าง PDF หนังสือที่มีเค้าโครงแบบเรียงพิมพ์ หรือแอปที่มีการเรนเดอร์ภาษาที่หายากแบบกำหนดเอง
การทำงานกับฟอนต์ใน iOS ต้องพิจารณาถึงประสิทธิภาพ ฟอนต์ที่ไม่ซ้ำกันแต่ละฟอนต์จะถูกโหลดเข้าสู่หน่วยความจำเมื่อเข้าถึงครั้งแรกและใช้ทรัพยากร ฟอนต์ระบบ San Francisco ถูกโหลดไว้ล่วงหน้าและไม่สร้างค่าใช้จ่ายเพิ่มเติม ฟอนต์กำหนดเองถูกโหลดจากไฟล์และถูกแคชโดยระบบหลังจากการโหลดครั้งแรก
แนะนำให้ จำกัดจำนวนฟอนต์ที่ไม่ซ้ำกัน ในแอปไว้ที่ 3-5 ตระกูล ฟอนต์แต่ละฟอนต์ใช้พื้นที่ตั้งแต่ 50 KB ถึง 2 MB ในหน่วยความจำ การใช้น้ำหนักที่แตกต่างกันของตระกูลเดียวกัน (regular, bold, medium) มีประสิทธิภาพมากกว่าการโหลดหลายตระกูลที่แตกต่างกัน
ระบบแคชอินสแตนซ์ UIFont ที่สร้างขึ้น ดังนั้นการเรียก UIFont.systemFont(ofSize: 16, weight: .regular) ซ้ำๆ จะไม่สร้างออบเจกต์ใหม่ อย่างไรก็ตาม UIFont(name:size:) สำหรับฟอนต์กำหนดเองไม่ได้ถูกแคชเสมอไป — แนะนำให้เก็บฟอนต์ที่ใช้บ่อยในคุณสมบัติแบบคงที่หรือ NSCache เพื่อหลีกเลี่ยงการโหลดซ้ำจากไฟล์
เมื่อลงทะเบียนฟอนต์แบบไดนามิกผ่าน CTFontManagerRegisterGraphicsFont กระบวนการอาจเป็นแบบอะซิงโครนัสหากไฟล์ฟอนต์ถูกดาวน์โหลดจากเครือข่าย ในกรณีนี้ UILabel หรือ UITextView ควรแสดงฟอนต์ระบบสำรองจนกว่าการโหลดจะเสร็จสมบูรณ์ หลังจากการลงทะเบียน ฟอนต์จะพร้อมใช้งานและหน้าจอจะอัปเดตการแสดงข้อความโดยอัตโนมัติ
คำถามที่พบบ่อย
ได้ UIFont และ CTFont รองรับ Toll-Free Bridging การแปลงทำได้โดยการแคสต์อย่างง่าย: UIFont as CTFont หรือ CTFont as UIFont ไม่มีค่าใช้จ่ายเพิ่มเติมหรือการคัดลอกข้อมูล — ทั้งสองคลาสชี้ไปยังออบเจกต์ฟอนต์เดียวกันในหน่วยความจำ
สำหรับคอมโพเนนต์ UI ทั้งหมด ใช้ UIFont มันถูกปรับให้เหมาะสมกับ UIKit รองรับ Dynamic Type และปรับขนาดอย่างถูกต้องเมื่อการตั้งค่าระบบเปลี่ยนแปลง CTFont เหมาะสมสำหรับการเรนเดอร์แบบกำหนดเองผ่าน Core Graphics หรือเมื่อต้องการการเข้าถึงเมตริกฟอนต์ระดับต่ำเท่านั้น
ใช้ UIFont.familyNames สำหรับรายการตระกูลและ UIFont.fontNames(forFamilyName:) สำหรับชื่อ PostScript เรียกโค้ดนี้ในโหมดดีบักและค้นหาฟอนต์ที่ต้องการ ชื่อ PostScript มักประกอบด้วยชื่อตระกูลและสไตล์: “SFProText-Regular”, “HelveticaNeue-Bold”
ได้ ผ่าน UIFontDescriptor คุณสามารถกำหนดค่าแกนแปรผัน: weight, width, slant อย่างไรก็ตาม API ของ UIFont สำหรับฟอนต์แปรผันมีจำกัดเมื่อเทียบกับ CTFontCopyVariation สำหรับการควบคุมแกนแปรผันอย่างสมบูรณ์ ใช้ Core Text และ CTFontCreateCopyWithVariation
สร้างพจนานุกรมแบบคงที่หรือ NSCache ด้วยคีย์ที่รวมชื่อและขนาด สำหรับฟอนต์ระบบ iOS แคชอินสแตนซ์โดยอัตโนมัติ แต่สำหรับฟอนต์กำหนดเองที่สร้างผ่าน UIFont(name:size:) แนะนำให้เก็บออบเจกต์ในแคชของแอปเพื่อหลีกเลี่ยงการโหลดซ้ำจากไฟล์ TTF
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ