iOS应用如何区分系统预装字体与动态加载字体?
区分iOS系统预装字体与动态加载字体的方案
嘿,刚好做过类似的需求,给你几个实用的方法来区分系统字体和你动态加载的自定义字体,还能轻松实现表格里的勾选标记功能:
方案一:提前缓存系统字体列表(最简单直接)
因为你的自定义字体是在App启动后才下载加载的,那我们可以在自定义字体加载之前,先把系统预装的字体列表缓存下来。之后只要对比当前字体是否在缓存列表里,就能快速区分了。
实现步骤:
- 在App启动初期(比如
AppDelegate的didFinishLaunchingWithOptions方法里)缓存系统字体:
// 可以定义全局变量或者用单例来存储这些缓存 var preloadedSystemFontFamilies: Set<String> = [] var preloadedSystemFontNames: Set<String> = [] func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 缓存系统字体家族名 preloadedSystemFontFamilies = Set(UIFont.familyNames) // 缓存所有系统字体的具体名称 UIFont.familyNames.forEach { familyName in let fontNames = UIFont.fontNames(forFamilyName: familyName) preloadedSystemFontNames.formUnion(fontNames) } return true }
- 判断字体是否为系统预装:
// 按字体家族名判断 func isSystemFontFamily(_ familyName: String) -> Bool { return preloadedSystemFontFamilies.contains(familyName) } // 按具体字体名判断 func isSystemFont(_ fontName: String) -> Bool { return preloadedSystemFontNames.contains(fontName) }
方案二:利用CoreText的注册字体API
CoreText提供了直接获取动态注册字体的方法,我们可以通过CTFontManagerCopyRegisteredFonts筛选出所有通过CTFontManagerRegisterGraphicsFont注册的自定义字体,剩下的就是系统预装字体了。
实现代码:
import CoreText func getDynamicallyInstalledFonts() -> Set<String> { var dynamicFonts = Set<String>() // 获取所有已注册的启用字体 guard let registeredFontDescriptors = CTFontManagerCopyRegisteredFonts(.enabled, nil) as? [CTFontDescriptor] else { return dynamicFonts } for descriptor in registeredFontDescriptors { // 检查该字体是否是动态注册的(非系统预装) if let isDynamicallyRegistered = CTFontDescriptorCopyAttribute(descriptor, kCTFontManagerRegisteredFontAttribute) as? Bool, isDynamicallyRegistered { // 获取字体名称 if let fontName = CTFontDescriptorCopyAttribute(descriptor, kCTFontNameAttribute) as? String { dynamicFonts.insert(fontName) } } } return dynamicFonts }
之后你可以用这个集合来对比,不在集合里的就是系统字体。
表格单元格添加勾选标记的技巧
你需要维护一个已安装自定义字体的列表(可以存在UserDefaults或者本地数据库里),每次调用install_font函数成功后,就把对应的字体名称/家族名添加到这个列表里。
在表格的cellForRowAt方法里:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "FontCell", for: indexPath) let font = availableFonts[indexPath.row] // availableFonts是你的可安装字体列表 // 设置字体名称等内容 cell.textLabel?.text = font.familyName // 判断是否已安装,显示勾选标记 let installedFonts = UserDefaults.standard.stringArray(forKey: "InstalledFonts") ?? [] if installedFonts.contains(font.familyName) { cell.accessoryType = .checkmark } else { cell.accessoryType = .none } return cell }
注意事项:
- 方案一要确保缓存系统字体的代码早于自定义字体加载的代码执行,不然缓存里会包含自定义字体,导致区分失效。
- 如果之后需要卸载自定义字体,记得同时更新已安装列表(方案一的缓存无需更新,因为它记录的是初始系统字体状态)。
内容的提问来源于stack exchange,提问作者Alexandru Vasiliu
相关产品推荐
相关产品推荐

