Reputation: 1444
I wonder if there is a way to load fonts from a Swift Package at the moment? The font files are there in the package but the compiled program can't locate them.
Upvotes: 6
Views: 3836
Reputation: 119646
From Swift 5.3, you can add any resources
to the target, including images, assets, fonts, zip, etc. Using the directory name will include all subfiles of the directory:
.target(
name: "ABUIKit",
dependencies: [],
resources: [.process("Resources") // <- this will add Resource directory to the target
]
),
Note that you should put the Resources
folder under sources/packageName
to make it recognizable.
You need to register fonts to make it work. So you can use frameworks like FontBlaster.
NOTE: You can always write your own code, but I prefer to use an existing framework and contribute my extra needs to them
So you call this somewhere early in the module's code (like some init method):
FontBlaster.blast(bundle: .module)
Then you can use the font inside or even outside of the module!
It will register all included fonts automatically. You can double-check the loaded fonts right after calling the blast method:
FontBlaster.loadedFonts.forEach { print("🔠", $0) }
Upvotes: 7
Reputation: 1226
Mojtaba Hosseini's answer is correct but in order to use the fonts of your package you need to register them also. You could do it with a little supporting function in a struct... I use this in my projects:
public struct Appearance {
/// Configures all the UI of the package
public static func configurePackageUI() {
loadPackageFonts()
}
static func loadPackageFonts() {
// All the filenames of your custom fonts here
let fontNames = ["Latinotype - Texta-Black.otf",
"Latinotype - Texta-BlackIt.otf",
"Latinotype - Texta-Bold.otf",
"Latinotype - Texta-BoldIt.otf",
"Latinotype - Texta-Book.otf",
"Latinotype - Texta-BookIt.otf",
"Latinotype - Texta-Heavy.otf",
"Latinotype - Texta-HeavyIt.otf",
"Latinotype - Texta-It.otf",
"Latinotype - Texta-Light.otf",
"Latinotype - Texta-LightIt.otf",
"Latinotype - Texta-Medium.otf",
"Latinotype - Texta-MediumIt.otf",
"Latinotype - Texta-Regular.otf",
"Latinotype - Texta-Thin.otf",
"Latinotype - Texta-ThintIt.otf",
]
fontNames.forEach{registerFont(fileName: $0)}
}
static func registerFont(fileName: String) {
guard let gFontRef = getFont(named: fileName) else {
print("*** ERROR: ***")
return
}
var errorRef: Unmanaged<CFError>? = nil
if !CTFontManagerRegisterGraphicsFont(gFontRef, &errorRef) {
print("*** ERROR: \(errorRef.debugDescription) ***")
}
}
static func getFont(named fileName: String) -> CGFont? {
let url = Bundle.module.url(forResource: fileName, withExtension: nil)
guard let gUrl = url,
let gFontData = NSData(contentsOf: gUrl),
let gDataProvider = CGDataProvider(data: gFontData),
let gFontRef = CGFont(gDataProvider) else {
print("*** ERROR: ***")
return nil
}
return gFontRef
}
}
Just remember to add the font filename in the array.
EDIT: I've updated my answer.
Upvotes: 9