1

I'm trying to change the Font and the tracking of a text in SwiftUI. So far I have created an extension for Text that sets the tracking.

extension Text {
    func setFont(as font: Font.MyFonts) -> Self {
        self.tracking(font.tracking)
    }
}

I have also created a View Modifier that sets the correct font from my enum

extension Text {
    func font(_ font: Font.MyFonts) -> some View {
        ModifiedContent(content: self, modifier: MyFont(font: font))
    }
}

struct MyFont: ViewModifier {
    let font: Font.MyFonts

    func body(content: Content) -> some View {
        content
            .font(.custom(font: font))
    }
}

static func custom(font: MyFonts) -> Font {
        return Font(font.font as CTFont)
    }

I can't seem to find any way to combine these, since the view modifier returns some View and the tracking can only be set on a Text. Is there any clever way to combine these so I can only set the view Modifier?

the enum of fonts look like this

extension Font {
    enum MyFonts {
        case huge
        case large
        case medium

        /// Custom fonts according to design specs
        var font: UIFont {
            var font: UIFont?
            switch self {
            case .huge: font = UIFont(name: AppFontName.book, size: 40)
            case .large: font = UIFont(name: AppFontName.book, size: 28
            case .medium: font = UIFont(name: AppFontName.book_cursive, size: 18)
            }
            return font ?? UIFont.systemFont(ofSize: 16)
        }

        var tracking: Double {
            switch self {
            case .huge:
                return -0.25
            default:
                return 0
            }
        }
    }

This is the app font name struct that I'm using

public struct AppFontName {

    static let book = "Any custom font name"
    static let book_cursive = "any custom font name cursive"
}
Giovanni Palusa
  • 1,197
  • 1
  • 16
  • 36

1 Answers1

0

I still have errors for missed .custom, but anyway seems the solution for your code is to use own Text.font instead of View.font, like

extension Text {
//    func font(_ font: Font.MyFonts) -> some View {
//        ModifiedContent(content: self, modifier: MyFont(font: font))
//    }

    func font(_ font: Font.MyFonts) -> Self {
        self.font(Font.custom(font: font))
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Ah, I missed that one too... custom only returns a Font `return Font(font.font as CTFont)` - so it doesn't do any magic... – Giovanni Palusa Dec 01 '21 at 09:35
  • In a function like this I could also add to call back to the `setFont()` function... but then this will be limited to be used only on `Text` - I guess I will have to settle with this and not use it as a general viewModifier – Giovanni Palusa Dec 01 '21 at 09:50