swiftui

Set System to always use Rounded Font?


In SwiftUI, is there a way to make the rounded version of the system font the default for all styles? I'm using one of the system styles (.body, .title, .headline, etc) for all text in the app.

For example, I can use this on a single Text view

Text("some text")
    .font(.system(.body, design: .rounded))

I'd like to avoid having to update every text view and field in my app like this. Is there some way to tell the environment to use the rounded design by default?


Solution

  • Starting with iOS 16.1+ and macOS 13.0+, you can use the fontDesign(_:) modifier to customize the font design within a SwiftUI view hierarchy.

    Here's an example demonstrating how to apply a rounded font design across the entire app:

    import SwiftUI
    
    @main
    struct MyDemoApp: App {
        var body: some Scene {
            WindowGroup {
                ContentView()
                    .fontDesign(.rounded)
            }
        }
    }
    

    However, this modifier does not affect the fonts used for navigation toolbar titles. To customize those, you need to configure their fonts using UINavigationBar.appearance(). A suitable location to set this configuration is in the AppDelegate class.

    AppDelegate.swift:

    import UIKit
    
    final class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
        func application(
            _ application: UIApplication,
            didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
        ) -> Bool {
            let largeTitleFont = UIFont.preferredFont(forTextStyle: .largeTitle)
            let newLargeFontDescriptor = largeTitleFont.fontDescriptor.withDesign(.rounded)?
                .withSymbolicTraits(.traitBold) ?? largeTitleFont.fontDescriptor
            let newLargeTitleFont = UIFont(descriptor: newLargeFontDescriptor, size: largeTitleFont.pointSize)
            UINavigationBar.appearance().largeTitleTextAttributes = [.font: newLargeTitleFont]
    
            let regularTitleFont = UIFont.preferredFont(forTextStyle: .headline)
            let newRegularFontDescriptor = regularTitleFont.fontDescriptor.withDesign(.rounded)?
                .withSymbolicTraits(.traitBold) ?? regularTitleFont.fontDescriptor
            let newRegularTitleFont = UIFont(descriptor: newRegularFontDescriptor, size: regularTitleFont.pointSize)
             UINavigationBar.appearance().titleTextAttributes = [.font: newRegularTitleFont]
    
            return true
        }
    }
    

    MyDemoApp.swift:

    import SwiftUI
    
    @main
    struct MyDemoApp: App {
        @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
        var body: some Scene {
            WindowGroup {
                ContentView()
                    .fontDesign(.rounded)
            }
        }
    }