FontBlaster registers every font in your bundle without touching a plist
Programmatically load custom fonts into your iOS, macOS and tvOS app.
At a glance
- What is it?
- FontBlaster is a Swift package that loads the fonts shipped inside an app at runtime, recursively, so you can skip listing them in UIAppFonts. It is small, MIT licensed, and after version 6.0 it demands iOS 17, macOS 14, tvOS 17 and Swift 5.9 or newer.
- Who is it for?
- FontBlaster is worth adopting when your app ships fonts that are decided at build time or come from a downloaded bundle, because it removes the plist bookkeeping and the mismatch between a font list and what the bundle actually contains. It is unnecessary when you have a handful of known fonts that a plist entry registers perfectly well, and its v6 platform floor of iOS 17, macOS 14 and tvOS 17 rules it out for apps that must support older systems.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 108 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The plist list of fonts and the files in the bundle drift apart
Apple's usual way to ship a custom font is to declare it in the application's property list, under the UIAppFonts key, and to keep that list in step with the files you copy into the bundle. The failure mode is mundane and common. A designer adds a font file, a build script copies it, someone forgets the plist, and the app runs with a fallback typeface and no error anywhere. FontBlaster removes the list. It automatically imports and loads all fonts in the app's bundles with one line of code, and the project describes itself as a way to stop importing custom fonts via property lists. The audience is any team shipping custom typography on Apple platforms, especially where the set of fonts is generated, downloaded, or selected per build rather than hand-maintained. For a fixed set of two or three fonts, the plist is fine, and this library is solving a problem you may not have.
The scan is recursive, and it follows nested bundles
The scanning behaviour is where the value sits. The feature list states that FontBlaster scans subdirectories and nested bundles recursively, which means a font sitting three folders deep inside a resource directory, or inside a bundle embedded in a framework, is still found. The supported formats are .ttf, .otf and .ttc. Registration is a single call with no arguments:
FontBlaster.blast() // Defaults to Bundle.main if no arguments are passedThat call covers the common case, since a custom bundle is usually lodged inside the main bundle, and the argument is only needed when the bundle in question is not reachable from the main bundle:
FontBlaster.blast(bundle: myCustomBundle)The recursive behaviour is also the reason the library needs to be careful about when it runs. Fonts are registered with the system at the moment the call happens, so calling blast() later than you intended means text drawn before that point still uses the fallback face, which is exactly what the sample project in the repository demonstrates by redrawing the view after the call.
Installing through Swift Package Manager or as one file
There are two supported routes, and the second one is unusual for a package. Through Swift Package Manager, the package is declared in the usual way:
.package(url: "https://github.com/ArtSabintsev/FontBlaster.git", from: "6.0.0")The manual route is simply to download the project and copy a single file, FontBlaster.swift, into your own project. That the library can be dropped in as one source file is a consequence of how small it is, and it matters for teams that cannot take a package dependency, for example because they vendor third-party code, or because they have a shared framework target where a package would be awkward. The repository layout supports that story, with a Sources directory, a Tests directory, a Package.swift file, an Example directory that contains an OpenSans folder of font resources, and a .swiftpm directory. The example project is a real integration reference rather than a toy, and the README explains its behaviour: the fonts are configured to load on demand when the navigation bar button is pushed, and the view redraws afterwards.
A completion handler variant returns the names that were loaded
If you need to know what was actually registered, an overloaded form of the method takes a completion handler that returns the loaded font names as an array of strings:
FontBlaster.blast() { fonts in
print(fonts) // fonts is an array of Strings containing font names
}
FontBlaster.blast(bundle: myCustomBundle) { fonts in
print(fonts) // fonts is an array of Strings containing font names
}This is more useful than it first appears, because the value of the whole approach is that nothing is declared up front, which also means nothing tells you what you got. A completion handler gives you the runtime truth, so you can log it, assert on it in a UI test, or fail a build check that a font is missing, instead of discovering the problem when a designer sees the wrong typeface. Debug output is available through a static switch that has to be set before the call:
FontBlaster.debugEnabled = true
FontBlaster.blast()The ordering requirement is explicit in the documentation, since the flag is read when the method runs.
Registered fonts are file-backed, so the file has to stay put
There is one operational constraint that catches people out, and the documentation states it plainly: registered fonts are file-backed, so you must not move or delete a font file after it has been loaded. This is a property of the platform rather than of the library, but the library makes it easy to trip over, because its whole model is to load fonts at runtime, often from a bundle that the application might later clean up or replace. A cache directory that is purged after registration, or a downloaded bundle that gets deleted on an update path, will leave you with a registered font whose backing file no longer exists. The safe pattern is to treat the bundle that contains the fonts as permanent for the lifetime of the process. This is a small thing, but it is the kind of detail that turns into a crash report on someone else's device, so it belongs in your integration notes.
Version 6 raised the floor and the licence stayed MIT
The release history shows one recent break and a long quiet stretch. Version 5.3.0, titled as a fix for macOS support, was published on 2022-05-20, and then version 6.0.0 arrived on 2026-07-07 with the title Modernized for SwiftPM and iOS 17, followed by 6.0.1 the next day. The requirements are stated as iOS 17.0 and above, tvOS 17.0 and above, macOS 14.0 and above, and Swift 5.9 and above, which is a substantial jump for anyone still supporting earlier systems. The last push was on 2026-07-08, the same date as the 6.0.1 release. The licence is MIT, and the repository carries a LICENSE file, which keeps the terms simple for a library you might vendor into a closed-source app. The cost of the upgrade is the platform floor rather than the API, since the documented surface is still the two method forms and one flag.
Against the plist, and against doing it yourself
The real alternative is the built-in route, declaring UIAppFonts in the property list and shipping the files in the bundle. The difference in approach is that the plist is a declaration of intent while FontBlaster is a scan of fact, and that difference shows up in the failure mode. The plist fails silently when it is stale, and the scan cannot be stale, at the cost of a runtime walk of your bundle and a platform requirement to load fonts at all. A second alternative is to write the registration loop yourself, a handful of CTFontManager calls, which gives you full control and zero dependencies but also gives you the recursion, the nested bundle handling and the .ttf, .otf and .ttc coverage that FontBlaster already implements. The project credits its inspiration to a solution Marco Arment proposed and wrote about for dynamic font loading on iOS, which is a useful piece of context: this is a small, well-scoped library that has been in the same shape for a long time, and version 6.0 modernised the packaging rather than the concept.
Editorial conclusion
FontBlaster is worth adopting when your app ships fonts that are decided at build time or come from a downloaded bundle, because it removes the plist bookkeeping and the mismatch between a font list and what the bundle actually contains. It is unnecessary when you have a handful of known fonts that a plist entry registers perfectly well, and its v6 platform floor of iOS 17, macOS 14 and tvOS 17 rules it out for apps that must support older systems. Before adopting it, confirm that the fonts you load are not moved or deleted after registration, since registered fonts are file-backed, and check that your deployment target clears the Swift 5.9 and platform version requirements that version 6.0 introduced.
Frequently asked questions
How do I load custom fonts with FontBlaster?
Call FontBlaster.blast(), which defaults to Bundle.main, or FontBlaster.blast(bundle: myCustomBundle) for a bundle that is not inside the main bundle. The library scans subdirectories and nested bundles recursively and supports .ttf, .otf and .ttc files.
What are the system requirements for FontBlaster 6?
The README lists iOS 17.0 and above, tvOS 17.0 and above, macOS 14.0 and above, and Swift 5.9 and above. Version 6.0.0 was published on 2026-07-07 and is described as modernized for SwiftPM and iOS 17.
Can FontBlaster load fonts from a bundle that is not in the main bundle?
Yes, by passing the bundle to the blast(bundle:) method. The feature list also states that fonts can be imported from remote bundles.
Is it safe to delete a font file after FontBlaster has loaded it?
No. The documentation states that registered fonts are file-backed, so you must not move or delete a font file after it has been loaded.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/artsabintsev-fontblaster)Was this useful?