如何在SwiftUI项目中通过单一位置全局修改全应用字体
SwiftUI 全局统一修改应用字体方案
完全可以通过单处配置实现全应用字体覆盖,分两种主流适配方案:
方案1:iOS 16+ 原生全局配置(推荐)
iOS 16及以上系统支持直接在App根视图添加font修饰符,全局覆盖所有未显式指定字体的文本控件,仅需修改一处即可生效:
@main struct CustomFontApp: App { var body: some Scene { WindowGroup { ContentView() // 全局默认字体,所有未单独设置font的文本都会继承该配置 .font(.custom("你的自定义字体名称", size: 16)) } } }
如果需要适配系统动态字体的不同文本样式(大标题、正文、注释等),可以统一封装Font扩展集中管理:
extension Font { static func appFont(for style: TextStyle) -> Font { switch style { case .largeTitle: return .custom("PingFangSC-Bold", size: 34, relativeTo: .largeTitle) case .title: return .custom("PingFangSC-Semibold", size: 28, relativeTo: .title) case .body: return .custom("PingFangSC-Regular", size: 17, relativeTo: .body) case .footnote: return .custom("PingFangSC-Regular", size: 13, relativeTo: .footnote) default: return .custom("PingFangSC-Regular", size: UIFont.preferredFont(forTextStyle: .init(rawValue: style.rawValue)).pointSize) } } }
使用时仅需调用.font(.appFont(for: .body))即可,所有样式统一管理,修改时仅需调整扩展内的配置。
方案2:iOS 13+ 全版本兼容方案
如果需要适配iOS 15及更低版本,可以通过方法交换Hook系统默认字体的创建逻辑,效果和UIKit中重写UIFontDescriptor的方案一致:
- 先添加UIFont扩展实现方法交换
import UIKit extension UIFont { static func enableGlobalCustomFont() { guard let originalMethod = class_getClassMethod(UIFont.self, #selector(systemFont(ofSize:weight:))), let swizzledMethod = class_getClassMethod(UIFont.self, #selector(customSystemFont(ofSize:weight:))) else { return } method_exchangeImplementations(originalMethod, swizzledMethod) } @objc private static func customSystemFont(ofSize size: CGFloat, weight: UIFont.Weight) -> UIFont { // 按字重匹配自定义字体的不同样式 let customFontName: String switch weight { case .bold, .heavy, .semibold: customFontName = "PingFangSC-Bold" default: customFontName = "PingFangSC-Regular" } // fallback到原方法避免自定义字体加载失败崩溃 return UIFont(name: customFontName, size: size) ?? customSystemFont(ofSize: size, weight: weight) } }
- 在App启动时调用交换方法,仅需配置一次全局生效
@main struct CustomFontApp: App { init() { UIFont.enableGlobalCustomFont() } var body: some Scene { WindowGroup { ContentView() } } }
注意事项
- 导入自定义字体后需确认在Info.plist中已添加
Fonts provided by application配置,且填写的字体名称正确,可通过打印UIFont.familyNames校验实际可用的字体名 - 单个控件如果需要单独使用其他字体,显式添加
font修饰符即可,优先级高于全局配置 - 方法交换方案需注意避免和其他第三方库的字体交换逻辑冲突,可添加标记位做兼容判断
内容的提问来源于stack exchange,提问作者Maharajan S
相关产品推荐
相关产品推荐

