SwiftUI 小技巧:如何读取 SwiftUI Font 的详细信息

字号、字体名称、粗体、斜体等属性,都能拿到
我见过不少开发者,甚至一些 AI 工具都说:我们无法从 SwiftUI 的 Font 中获取任何具体信息。在此之前,我也一直是这么认为的。
但今天,我突然非常需要读取字体信息,主要是字体名称、字号,以及是否为粗体或斜体。
我的应用是多平台项目,所以我实在不想为此退回 UIKit 。如果使用 UIFont,到了 macOS 上又要通过 #if os(macOS) 切换成对应的 NSFont,还得额外维护一套平台判断。
与其花时间写这段条件编译,我决定对 Font 按下 Command + Click,顺着定义一路查看它公开的 API。
结果还真让我发现了一个很实用的方法。
使用 resolve(in:)
这个方法就是 resolve(in:)。
它适用于 iOS 26、iPadOS 26、macOS 26、Mac Catalyst 26、tvOS 26、watchOS 26 和 visionOS 26 及以上系统,返回一个 Font.Resolved 实例。
我之前知道 Color 有 resolve 方法,现在发现字体也有对应能力,确实很方便。
Font.Resolved 提供了不少可以直接读取的属性,例如:
isBold:是否为粗体isItalic:是否为斜体isMonospaced:是否为等宽字体pointSize:字号weight:字重
更重要的是,我们还能拿到 ctFont。
前面列出的属性,可以看作 SwiftUI 帮我们从 CTFont 中整理出的常用信息。拿到 ctFont 后,还能继续通过 Core Text API 获取更多内容。
例如,可以使用 CTFontCopyFullName 获取字体的完整名称,或者用 CTFontCopyCharacterSet 获取该字体支持的 Unicode 字符集合。熟悉 Core Text 的开发者应该知道,CTFont 能提供的信息非常丰富。
使用示例
调用 resolve(in:) 时,需要传入一个 Font.Context。这个 Context 从哪里来?答案还是我们熟悉的 EnvironmentValues。
可以通过 fontResolutionContext 从 Environment 中读取:
swift
struct FontAttributeDemo: View {
@Environment(\.fontResolutionContext) private var fontContext
var body: some View {
List {
// 从 SwiftUI Font 中读取属性:
// 1. 通过 EnvironmentValues/fontResolutionContext 获取 Font.Context
// 2. 调用 font.resolve(in:)
let font = Font.system(size: 12, weight: .bold, design: .monospaced)
.bold().italic()
let resolved = font.resolve(in: self.fontContext)
Section {
// 还可以读取其他 CTFont 属性,
// 例如本地化名称、支持的字符集合等。
LabeledContent(
"字体名称",
value: CTFontCopyFullName(resolved.ctFont) as String
)
LabeledContent("字号", value: "\(resolved.pointSize)")
LabeledContent("字重", value: "\(resolved.weight)")
LabeledContent("是否为粗体", value: "\(resolved.isBold)")
LabeledContent("是否为斜体", value: "\(resolved.isItalic)")
LabeledContent("字宽", value: "\(resolved.width)")
LabeledContent("行间距", value: "\(resolved.leading)")
LabeledContent("是否为等宽字体", value: "\(resolved.isMonospaced)")
LabeledContent(
"是否使用小型大写字母显示小写字符",
value: "\(resolved.isLowercaseSmallCaps)"
)
LabeledContent(
"是否使用小型大写字母显示大写字符",
value: "\(resolved.isUppercaseSmallCaps)"
)
LabeledContent("是否使用小型大写字母", value: "\(resolved.isSmallCaps)")
} header: {
Text("Font.system(size: 12, weight: .bold, design: .monospaced).bold().italic()")
.font(.caption)
.fontWeight(.semibold)
}
}
}
}
这里的关键步骤只有两个:
- 使用
@Environment(\.fontResolutionContext)获取当前环境中的字体解析上下文。 - 调用
font.resolve(in: fontContext),得到Font.Resolved。
为什么需要 Context?因为 SwiftUI 的 Font 不一定代表一套固定不变的字体参数。像 Dynamic Type、平台环境和字体配置等因素,都可能影响它最终解析出来的结果。因此,resolve(in:) 需要结合当前环境,给出实际生效的字体信息。
这也意味着:如果你要观察用户调整文字大小后的结果,应该在对应 View 的 Environment 中重新解析,而不是把某一次得到的 Font.Resolved 当成永久不变的数据。
其他支持 resolve 的 SwiftUI 类型
除了 Font,SwiftUI 中还有其他类型提供类似的 resolve 方法,例如:
当你需要知道某个 SwiftUI 抽象值在当前环境中最终会呈现为什么具体结果时,可以先看看对应类型是否提供了 resolve API。
最后说两句
以前,如果想从 SwiftUI 的 Font 中读取具体属性,往往要借助 UIFont 或 NSFont。从 iOS 26 开始,Font.resolve(in:) 为多平台 SwiftUI 项目提供了一套更直接、更统一的方案。
它既能快速读取字号、字重、粗体和斜体等常用属性,也能通过 ctFont 继续访问 Core Text 提供的完整字体信息。
如果你的应用仍需支持 iOS 26 之前的系统,就要通过可用性判断隔离这段代码,并为旧系统保留兼容方案。
我是小侯爷。 在帝都北京工作,喜欢iOS、Flutter、Android、React。 最近打算跳槽,正在找新的工作,欢迎大家给内推哦。 如果读完觉得有收获的话,记得点赞哦