12

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?

5
  • it has a .font(). // font(Font(CTFont)) declaration Commented Nov 13, 2019 at 18:02
  • 1
    Try approach from my answer for this post Commented Nov 13, 2019 at 18:31
  • @Asperi thank you for the link. The proposed solution is very simple and effective. However, it does not change all the Text Views to a new font. For example the title in the navigationbar is not updated with the new font. Commented Nov 14, 2019 at 12:41
  • 1
    NavigationView, actually, is a special case, for now it can be configured only via UINavigationBar.appearance(). Eg. for font is UINavigationBar.appearance().largeTitleTextAttributes = [.font: UIFont(name: "Arial", size: 32)!] Commented Nov 14, 2019 at 13:16
  • 1
    Okay thanks, that works for the large titles. And for the inline titles I use UINavigationBar.appearance().titleTextAttributes = [.font : UIFont(name: Fonts.plexSemiBold, size: 20)!] And for the back Buttons I guess I use .navigationBarBackButtonHidden(true) and implement a custom NavigationBarItem. Then all the text should be updated. Kinda of a pain but it works. Commented Nov 14, 2019 at 13:24

3 Answers 3

2

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)
}


Sign up to request clarification or add additional context in comments.

2 Comments

Any idea how this would be applied to a SwiftUI Label(…)?
hey @DeveloBär (great name btw) you can just copy the method in a similar manner with the signature func Label(_ titleKey: LocalizedStringKey, image name: String) -> SwiftUI.Label { .init( ... ) }
1

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)

Comments

-1

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))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.