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

如何使用Swift从URL下载.ttf字体文件并在App中使用

iOS 实现从URL下载TTF字体并动态使用的方案

实现步骤

1. 下载字体文件到本地沙盒

使用系统内置URLSession完成下载,可将文件存在沙盒Cache或Documents目录避免重复下载:

func downloadFont(from url: URL, completion: @escaping (URL?, Error?) -> Void) {
    let task = URLSession.shared.downloadTask(with: url) { tempLocalUrl, response, error in
        guard let tempLocalUrl = tempLocalUrl, error == nil else {
            completion(nil, error)
            return
        }
        // 移动到持久化存储目录
        let cacheDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
        let savedUrl = cacheDir.appendingPathComponent(url.lastPathComponent)
        do {
            if FileManager.default.fileExists(atPath: savedUrl.path) {
                try FileManager.default.removeItem(at: savedUrl)
            }
            try FileManager.default.moveItem(at: tempLocalUrl, to: savedUrl)
            completion(savedUrl, nil)
        } catch {
            completion(nil, error)
        }
    }
    task.resume()
}

2. 动态注册字体到当前App进程

使用CoreText框架内置的CTFontManagerRegisterFontsForURL方法完成注册,注册成功后即可和内置字体一样使用:

import CoreText

func registerFont(from fileUrl: URL) -> Bool {
    guard FileManager.default.fileExists(atPath: fileUrl.path) else {
        return false
    }
    var error: Unmanaged<CFError>?
    // .process参数表示仅当前App进程可用,无需系统级权限
    let registerSuccess = CTFontManagerRegisterFontsForURL(fileUrl as CFURL, .process, &error)
    if let error = error?.takeRetainedValue() {
        print("字体注册失败: \(error.localizedDescription)")
    }
    return registerSuccess
}

提示:同名字体重复注册会返回失败,可提前通过CTFontManagerCopyAvailablePostScriptNames检查字体是否已注册,减少不必要操作。

3. 读取字体名称并使用

字体的文件名和实际可用的PostScript名称可能不一致,需要先读取字体的真实名称再初始化UIFont:

// 从本地字体文件读取PostScript名称
func getFontPostScriptName(from fileUrl: URL) -> String? {
    guard let fontData = try? Data(contentsOf: fileUrl),
          let dataProvider = CGDataProvider(data: fontData as CFData),
          let cgFont = CGFont(dataProvider) else {
        return nil
    }
    return cgFont.postScriptName as String?
}

// 使用示例
if let fontName = getFontPostScriptName(from: savedFontUrl),
   let customFont = UIFont(name: fontName, size: 16) {
    // 赋值给需要自定义字体的控件
    targetLabel.font = customFont
}

注意事项

  • 动态注册的字体仅在当前App进程内有效,App重启后需要重新注册,无需重复下载已存储在沙盒的字体文件
  • 无需在Info.plist的UIAppFonts项中配置动态下载的字体,该配置仅对打包内置到App的字体生效
  • 支持TTF、OTF格式的字体,注册失败优先检查字体文件是否损坏、是否有合法使用权
  • Objective-C实现逻辑完全一致,对应API为NSURLSession、CTFontManagerRegisterFontsForURL,无系统版本兼容问题,支持iOS 12及以上所有版本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 07:15:05