133 lines
4.0 KiB
Swift
133 lines
4.0 KiB
Swift
//
|
||
// FontManager.swift
|
||
// QuickLocation
|
||
//
|
||
// Created by 八条 on 2026/8/5.
|
||
//
|
||
|
||
import UIKit
|
||
|
||
/// 项目自定义字体样式
|
||
enum AppFont {
|
||
/// 荆南波波黑-Bold
|
||
case boboBold
|
||
/// 字魂扁黑体
|
||
case ziHunBianHei
|
||
/// 优设标题黑
|
||
case youSheBiaoTiHei
|
||
|
||
/// 候选字体名(按优先级;部分字体 PostScript 名异常,需多试)
|
||
var candidateNames: [String] {
|
||
switch self {
|
||
case .boboBold:
|
||
// TTF Full Name 为「荆南波波黑 Bold」,PostScript 名为异常的「-Bold」
|
||
return ["荆南波波黑 Bold", "荆南波波黑-Bold", "JingNanBoBoHei-Bold"]
|
||
case .ziHunBianHei:
|
||
return ["zihunbiantaoti", "字魂扁黑体"]
|
||
case .youSheBiaoTiHei:
|
||
// PostScript / Full Name 均为 YouSheBiaoTiHei
|
||
return ["YouSheBiaoTiHei", "优设标题黑"]
|
||
}
|
||
}
|
||
|
||
var familyName: String? {
|
||
switch self {
|
||
case .boboBold: return "荆南波波黑"
|
||
case .ziHunBianHei: return nil
|
||
case .youSheBiaoTiHei: return "YouSheBiaoTiHei"
|
||
}
|
||
}
|
||
|
||
var fileName: String {
|
||
switch self {
|
||
case .boboBold: return "荆南波波黑-Bold.ttf"
|
||
case .ziHunBianHei: return "zihunbiantaoti-r.ttf"
|
||
case .youSheBiaoTiHei: return "优设标题黑_猫啃网.ttf"
|
||
}
|
||
}
|
||
|
||
var fallbackWeight: UIFont.Weight {
|
||
switch self {
|
||
case .boboBold: return .bold
|
||
case .ziHunBianHei: return .medium
|
||
case .youSheBiaoTiHei: return .bold
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 统一字体管理:取字体 + 启动注册
|
||
enum FontManager {
|
||
|
||
private static var resolvedNames: [AppFont: String] = [:]
|
||
private static var didRegister = false
|
||
|
||
/// 按样式与字号取字体,失败回退系统字体
|
||
static func font(_ style: AppFont, size: CGFloat) -> UIFont {
|
||
ensureRegistered()
|
||
if let name = resolvedFontName(for: style),
|
||
let custom = UIFont(name: name, size: size) {
|
||
return custom
|
||
}
|
||
return .systemFont(ofSize: size, weight: style.fallbackWeight)
|
||
}
|
||
|
||
static func boboBold(_ size: CGFloat) -> UIFont {
|
||
font(.boboBold, size: size)
|
||
}
|
||
|
||
static func ziHunBianHei(_ size: CGFloat) -> UIFont {
|
||
font(.ziHunBianHei, size: size)
|
||
}
|
||
|
||
static func youSheBiaoTiHei(_ size: CGFloat) -> UIFont {
|
||
font(.youSheBiaoTiHei, size: size)
|
||
}
|
||
|
||
/// 注册 Bundle 内自定义字体(可重复调用)
|
||
static func registerCustomFonts() {
|
||
for style in [AppFont.boboBold, .ziHunBianHei, .youSheBiaoTiHei] {
|
||
if let registered = UIFont.loadFontName(style.fileName), !registered.isEmpty {
|
||
// 忽略异常 PostScript(如 "-Bold"),优先用可实例化的名
|
||
if !registered.hasPrefix("-"),
|
||
UIFont(name: registered, size: 12) != nil {
|
||
resolvedNames[style] = registered
|
||
continue
|
||
}
|
||
}
|
||
if let name = resolveAvailableName(for: style) {
|
||
resolvedNames[style] = name
|
||
}
|
||
}
|
||
didRegister = true
|
||
}
|
||
|
||
private static func ensureRegistered() {
|
||
guard !didRegister else { return }
|
||
registerCustomFonts()
|
||
}
|
||
|
||
private static func resolvedFontName(for style: AppFont) -> String? {
|
||
if let cached = resolvedNames[style] { return cached }
|
||
if let name = resolveAvailableName(for: style) {
|
||
resolvedNames[style] = name
|
||
return name
|
||
}
|
||
return nil
|
||
}
|
||
|
||
private static func resolveAvailableName(for style: AppFont) -> String? {
|
||
for name in style.candidateNames {
|
||
if UIFont(name: name, size: 12) != nil {
|
||
return name
|
||
}
|
||
}
|
||
if let family = style.familyName {
|
||
let names = UIFont.fontNames(forFamilyName: family)
|
||
if let first = names.first {
|
||
return first
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
}
|