Skip to content

Instantly share code, notes, and snippets.

@mackoj
Last active June 11, 2024 07:19
Show Gist options
  • Save mackoj/2a7e62fdae87b692e81601114cc514d0 to your computer and use it in GitHub Desktop.
Save mackoj/2a7e62fdae87b692e81601114cc514d0 to your computer and use it in GitHub Desktop.
This simplifies the process of loading custom fonts that are resources in an iOS Apple SPM Package (Swift Package Manager).
import Foundation
import UIKit
public typealias FontNameExt = (name: String, ext: String)
public func autoRegisteringFont(_ fontNames: [FontNameExt], _ spmBundleName : String) throws {
guard let spmBundle = Bundle(bundleName: spmBundleName) else {
throw("Fail to find bundle(\(spmBundleName).bundle) in your app bundle.")
}
try fontURLs(for: fontNames, in: spmBundle).forEach { try registerFont(from: $0) }
}
extension Bundle {
convenience init?(bundleName: String) {
self.init(path: "\(Bundle.main.bundlePath)/\(bundleName).bundle")
}
}
func fontURLs(for fontNames: [FontNameExt], in bundle: Bundle) -> [URL] {
return fontNames.compactMap { police in
bundle.url(forResource: police.name, withExtension: police.ext)
}
}
func registerFont(from url: URL) throws {
guard let fontDataProvider = CGDataProvider(url: url as CFURL) else {
throw("Could not get reference to font data provider.")
}
guard let font = CGFont(fontDataProvider) else {
throw("Could not get font from CoreGraphics.")
}
var error: Unmanaged<CFError>?
guard CTFontManagerRegisterGraphicsFont(font, &error) else {
throw("Error registering font: \(dump(error)!).")
}
}
@mackoj
Copy link
Author

mackoj commented Apr 25, 2022

@mrugeshtank Thanks for the message but I have fonts in multiple modules and the loader is in its own module. I can't use "Bundle.module" but I have to specify it. I have to rework my code anyways so I will take inspiration from your gist and my constraint.

Thanks,

@mrugeshtank
Copy link

mrugeshtank commented Apr 26, 2022

Didn't get that.
I'm using this in SPM and made public func to register fonts in SPM. Calling that public func method from app's didFinishLaunchingWithOptions and working like charm.
I think SPM is the module itself. Are you having multiple Modules in a single SPM?

Take a look at Access a Resource in Code

@mackoj
Copy link
Author

mackoj commented Nov 23, 2023

Yes 126 SPM modules that means 126 library targets all in the same Package.swift

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment