You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS SwiftUI应用中Swift Package Manager自定义字体配置失效问题及正确实现方案咨询

解决SPM自定义字体在SwiftUI中不生效的问题

我之前在SPM里配置自定义字体时也踩过几乎一模一样的坑,你的代码框架没问题,主要是两个关键环节没处理好——字体没有注册到系统和可能用错了字体的实际内部名称。下面是一步步的解决办法:

1. 先确认字体的正确内部名称(最容易踩的坑)

很多人会直接用字体文件名作为Font.custom()的参数,但字体的实际内部名称和文件名经常不一样(比如文件名是Gotham-Bold.otf,实际名称可能是Gotham Bold)。如果名称不匹配,系统找不到字体,就会 fallback 到一个默认的非SF字体,这就是你看到的异常现象。

怎么确认正确名称:

  • 把你的.otf字体拖进Mac的「字体册」
  • 右键字体 → 「显示信息」
  • 查看「全名」或者「PostScript名称」,这个才是你要在代码里用的字符串

2. 在SPM包中添加字体注册逻辑

SPM不会自动帮你把包内的字体注册到iOS系统中,必须手动写代码完成注册。在你的MyAwesomePackage里添加一个字体注册工具:

import UIKit

public enum FontRegistrar {
    public static func registerCustomFonts() {
        // 替换成你从字体册里拿到的实际字体名称
        let fontInfos = [
            ("Gotham-Bold", "otf"),
            ("Gotham-Book", "otf"),
            ("Gotham-Medium", "otf")
        ]
        
        for (fontName, extensionType) in fontInfos {
            guard let fontURL = Bundle.module.url(forResource: fontName, withExtension: extensionType) else {
                print("❌ 找不到字体文件: \(fontName).\(extensionType)")
                continue
            }
            
            do {
                let fontData = try Data(contentsOf: fontURL)
                guard let dataProvider = CGDataProvider(data: fontData as CFData) else {
                    print("❌ 无法创建字体数据提供者: \(fontName)")
                    continue
                }
                
                guard let cgFont = CGFont(dataProvider) else {
                    print("❌ 无法初始化CGFont: \(fontName)")
                    continue
                }
                
                var registrationError: Unmanaged<CFError>?
                if !CTFontManagerRegisterGraphicsFont(cgFont, &registrationError) {
                    if let error = registrationError?.takeRetainedValue() {
                        let errorDesc = CFErrorCopyDescription(error)
                        print("❌ 注册字体失败 \(fontName): \(errorDesc ?? "未知错误" as CFString)")
                    }
                } else {
                    print("✅ 成功注册字体: \(fontName)")
                }
            } catch {
                print("❌ 加载字体数据失败 \(fontName): \(error.localizedDescription)")
            }
        }
    }
}

这里用Bundle.module是SPM提供的专门用来访问包内资源的方式,能确保正确找到字体文件。

3. 在主应用启动时调用注册方法

打开你的主应用的App结构体,在初始化方法里调用注册逻辑,确保字体在应用启动时就被注册:

import MyAwesomePackage
import SwiftUI

@main
struct YourAppName: App {
    init() {
        // 启动时注册SPM里的自定义字体
        FontRegistrar.registerCustomFonts()
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

4. 修正CustomFontType中的字体名称

把CustomFontType里的customFont值替换成你从字体册里拿到的实际名称,比如如果实际名称是Gotham Bold,就改成:

var customFont: String {
    switch self {
    case .header: "Gotham Bold" // 替换成实际名称
    case .body: "Gotham Book"
    case .link: "Gotham Medium"
    }
}

最后验证

运行你的应用,现在自定义字体应该能正常显示了。如果还是有问题,可以看控制台的打印日志,排查是找不到字体文件还是注册失败,针对性解决。

内容的提问来源于stack exchange,提问作者Roland Lariotte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:12:48