Change default system font in SwiftUI

9.3k views Asked by At

I'm trying to set a custom default font in my SwiftUI app. I tried several suggestions from this thread Set a default font for whole iOS app?.

However, none of those seem to work with SwiftUI. For example with this approach:

// Constants.swift
struct Fonts {
    static var plex = "IBMPlexMono-Text"
}


// FontExtension.swift
extension UILabel {
    var substituteFontName : String {
        get { return self.font.fontName }
        set { self.font = UIFont(name: Fonts.plex, size: 17)! }
    }

}

// AppDelegate.swift in didFinishLaunchingWithOptions-function
UILabel.appearance().substituteFontName = Fonts.plex

When I start the app, the custom font appears for a split second and then changes back to the default font by Apple. Why does it change back to Apple's font and how can it be done permanently?

Is it maybe possible with an extension on Text-View?

3

There are 3 answers

0
Edi On

You can have:

extension Font {
    static let mediumFont = Font.custom("Sans-Regular", size: Font.TextStyle.subheadline.size, relativeTo: .caption)
    static let mediumSmallFont = Font.custom("Sans-Regular", size: Font.TextStyle.footnote.size, relativeTo: .caption)
    static let smallFont = Font.custom("Sans-Regular", size: Font.TextStyle.caption.size, relativeTo: .caption)
    static let verySmallFont = Font.custom("Sans-Regular", size: Font.TextStyle.caption2.size, relativeTo: .caption)
}

extension Font.TextStyle {
    var size: CGFloat {
        switch self {
        case .largeTitle: return 60
        case .title: return 48
        case .title2: return 34
        case .title3: return 24
        case .headline, .body: return 18
        case .subheadline, .callout: return 16
        case .footnote: return 14
        case .caption: return 12
        case .caption2: return 10
        @unknown default:
            return 8
        }
    }
}

and use it like this:

Text("Edit Profile")
   .font(.mediumSmallFont)
2
yspreen On

this is the closest I could find to have a self-contained swift file that will change the font everywhere. make sure to call Font.setup in the app delegate on launch:

//
//  Font.swift
//  Hockey
//
//  Created by @yspreen on 11/11/22.
//

import SwiftUI

extension Font {
    static var brand = Font
        .custom("Some Font", size: UIFont.preferredFont(
            forTextStyle: .body
        ).pointSize)

    static func setUp() {
        let appearance = UINavigationBar.appearance()
        let largeTitle = UIFont.preferredFont(
            forTextStyle: .largeTitle
        ).pointSize
        let body = UIFont.preferredFont(
            forTextStyle: .body
        ).pointSize
        let caption1 = UIFont.preferredFont(
            forTextStyle: .caption1
        ).pointSize

        print(UIFont.preferredFont(forTextStyle: .largeTitle))
        appearance.largeTitleTextAttributes = [
            .font : UIFont(
                name: "SomeFont-Bold", size: largeTitle
            )!
        ]
        appearance.titleTextAttributes = [
            .font : UIFont(
                name: "SomeFont-Medium", size: body
            )!
        ]

        UITabBarItem.appearance().setTitleTextAttributes([.font: UIFont(name: "SomeFont-Regular", size: caption1)!], for: .normal)
        UITabBarItem.appearance().setTitleTextAttributes([.font: UIFont(name: "SomeFont-Regular", size: caption1)!], for: .selected)
    }
}

func Text(_ content: any StringProtocol) -> SwiftUI.Text {
    .init(content).font(.brand)
}

func TextField(_ titleKey: LocalizedStringKey, text: Binding<String>, axis: Axis = .horizontal) -> some View {
    SwiftUI.TextField(titleKey, text: text, axis: axis).font(.brand)
}


0
Shivani Bajaj On

You can use a custom font like this:

Font.custom("Font-Family-Name", size: fontSize)

Example:

Text("Testing")
.font(Font.custom("Font-Family-Name", size: 16))

For using the font anywhere in the app, create a structure with as follows. Be sure to import SwiftUI in the file that will contain the font structure as:

import SwiftUI

struct AppFont {
    static func commonFont(fontSize: CGFloat) -> Font {
        return Font.custom("Font-Family-Name", size: fontSize)
    }
}

Now you can use them anywhere in the app like this:

Text("Testing")
.font(AppFont.commonFont(fontSize: 16))