# What can go wrong when using custom fonts in SwiftUI

This blog post is targeting SDK developers who bundle custom fonts in their package/library/framework and these [fonts shall be used in reusable SwiftUI views](https://developer.apple.com/documentation/swiftui/applying-custom-fonts-to-text).

I will explain an issue observable when using font weight related view modifiers (like `bold`) on a non-registered custom font.  

Let's assume you added the [Open Sans](https://fonts.google.com/specimen/Open+Sans) true type font files to your bundle
- OpenSans-Regular.ttf
- OpenSans-Bold.ttf
- ...

You also provide reusable SwiftUI views which shall automatically leverage the custom font. To do so you can pass the result of `Font.custom(:size)` to the `font` view modifier. 

```Swift
struct ReusableView: View {
    var body: some View {
        Text("Use Font.custom directly")
            .font(.custom("OpenSans-Regular", size: 17))
            .bold()
    }
}
```

If you use the `bold` view modifier then SwiftUI is smart enough to load OpenSans-Bold.

![Correct bold font when registered](https://cdn.hashnode.com/res/hashnode/image/upload/v1647554656186/7zgMUzaK5.png)

This all works well as long as the app developer did not forget to register the font in the app for use.

```Swift
Font.registerOpenSans()

extension Font {
    static func registerOpenSans() {
        self.register(name: "OpenSans-Regular", withExtension: "ttf")
        self.register(name: "OpenSans-Bold", withExtension: "ttf")
        // ...
    }

    static func register(name: String, withExtension: String) {
        let fontURL = Bundle.main.url(forResource: name, withExtension: withExtension)!
        var error: Unmanaged<CFError>?
        CTFontManagerRegisterFontsForURL(fontURL as CFURL, .process, &error)
        if let error = error {
            print(error.takeUnretainedValue())
        }
    }
}
```

So what if the app developer forgot to register the font?

![Fallback without bold](https://cdn.hashnode.com/res/hashnode/image/upload/v1647554708864/DoxBqnThP.png)

You might expected that the **bold** font weight would still gets applied. But this is not the case. Apple Bug ?

To ensure that the font weight gets applied, no matter what, I recommend to use an extension. This extension either loads the font or fallbacks to the system font.

```
extension Font {
    /// get "Open Sans" font or fallbacks to the system font in case the custom font was not registered
    /// - Parameter size: size of font
    /// - Returns: "Open Sans" font (or sytem font as fallback)
    static func openSans(size: CGFloat) -> Font {
        guard UIFont.familyNames.contains("Open Sans") else {
            return Font.system(size: size)
        }
        return .custom("OpenSans-Regular", size: size)
    }
}
```

This will ensure that SwiftUI will be able to apply font weight even to a fallback font.

![Fallback honors bold font weight](https://cdn.hashnode.com/res/hashnode/image/upload/v1647555536112/e7NiIUlgR.png)

```Swift
struct ReusableView: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Use extension with fallback handling")
                .font(.openSans(size: 17))
                .bold()

            Text("Use Font.custom directly")
                .font(.custom("OpenSans-Regular", size: 17))
                .bold()
        }
    }
}
```

Of course the result is the same in case the font was registered.

![Works well when font is registered](https://cdn.hashnode.com/res/hashnode/image/upload/v1647555550249/hPgQZ37t2.png)
