How to use custom fonts in SwiftUI
In this article, I will show you how to build a custom font modifier CustomFontModifier in SwiftUI, which can be used for typography in your iOS app.
Text("Juhu!")
.customFont(.bold(size: .h1))Creating a custom Font
When building an app using a custom font, I’ve found that creating a custom font modifier CustomFontModifier is the best solution.
To implement this, start by creating a new file Font.swift, where we define our custom font, alongside it’s typographic sizes:
import SwiftUI
enum Font {
case light(size: Size)
case regular(size: Size)
case medium(size: Size)
case bold(size: Size)
enum Size: CGFloat {
case h1 = 21
case h2 = 16
case h3 = 14
case h4 = 12
}
var font: UIFont {
switch self {
case let .light(size):
return UIFontMetrics(forTextStyle: .body).scaledFont(for: R.font.osloSansLight(size: size.rawValue)!)
case let .regular(size):
return UIFontMetrics(forTextStyle: .body).scaledFont(for: R.font.osloSansRegular(size: size.rawValue)!)
case let .medium(size):
return UIFontMetrics(forTextStyle: .body).scaledFont(for: R.font.osloSansMedium(size: size.rawValue)!)
case let .bold(size):
return UIFontMetrics(forTextStyle: .body).scaledFont(for: R.font.osloSansBold(size: size.rawValue)!)
}
}
}I’ve placed my inside /Resources , and access it with the
static func osloSansRegular(size: CGFloat) -> UIFont?function. In my implementation, I am using UIFontMetrics to support Dynamic Type. If this behavior is not wanted, you could simply return the font directly:
var font: UIFont {
switch self {
case let .light(size):
return R.font.osloSansLight(size: size.rawValue)!
case let .regular(size):
return R.font.osloSansRegular(size: size.rawValue)!
case let .medium(size):
return R.font.osloSansMedium(size: size.rawValue)!
case let .bold(size):
return R.font.osloSansBold(size: size.rawValue)!
}
}Custom Font Modifier
In a new file CustomFontModifier.swift, we implement the custom modifier, accepting a Fontand applying it the the content:
import SwiftUI
struct CustomFontModifier: ViewModifier {
var font: Font
func body(content: Content) -> some View {
let uiFont = font.font
return content.font(.custom(uiFont.fontName, size: uiFont.pointSize))
}
}
extension View {
func customFont(_ font: Font) -> some View {
self.modifier(CustomFontModifier(font: font))
}
}Usage
With our custom font modifier, we can apply it to all components that require our custom font:
Text("Custom Font Engaged")
.customFont(.regular(size: .h2))