45

I have a UIViewRepresentable with a UITextView and I want to set the font on the UITextView using the current Font from the SwiftUI environment. I just need a simple init like:

UIFont(_ swiftUIFont: Font)

But I can't find any such thing. And the Font type doesn't seem to have any information I can use to try to implement one. Anyone know of a way to convert between the two font representations?

Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
Richard Venable
  • 8,310
  • 3
  • 49
  • 52
  • unfortunately, not yet (at least, I didn't find any way), fill the radar ... – user3441734 Feb 04 '20 at 10:27
  • Keep in mind: `SwiftUI.Font` is a `View`, where `UITextView.font` is a UIFont – nine stones Feb 07 '20 at 17:39
  • 8
    @ninestones `SwiftUI.Font` is just a plain `Struct` conforms to `Equatable` and `Hashable`, not a `View`: https://developer.apple.com/documentation/swiftui/font – Jonny Jun 27 '20 at 06:23

3 Answers3

17

A bit of a hack but works (doing the other direction is left as an exercise to the reader).

extension UIFont {
    class func preferredFont(from font: Font) -> UIFont {
        let uiFont: UIFont
        
        switch font {
        case .largeTitle:
            uiFont = UIFont.preferredFont(forTextStyle: .largeTitle)
        case .title:
            uiFont = UIFont.preferredFont(forTextStyle: .title1)
        case .title2:
            uiFont = UIFont.preferredFont(forTextStyle: .title2)
        case .title3:
            uiFont = UIFont.preferredFont(forTextStyle: .title3)
        case .headline:
            uiFont = UIFont.preferredFont(forTextStyle: .headline)
        case .subheadline:
            uiFont = UIFont.preferredFont(forTextStyle: .subheadline)
        case .callout:
            uiFont = UIFont.preferredFont(forTextStyle: .callout)
        case .caption:
            uiFont = UIFont.preferredFont(forTextStyle: .caption1)
        case .caption2:
            uiFont = UIFont.preferredFont(forTextStyle: .caption2)
        case .footnote:
            uiFont = UIFont.preferredFont(forTextStyle: .footnote)
        case .body:
            fallthrough
        default:
            uiFont = UIFont.preferredFont(forTextStyle: .body)
        }
        
        return uiFont
    }
}
Luke Howard
  • 469
  • 5
  • 5
  • 8
    This does not support custom font designs (rounded, etc), custom sizes/weights or custom fonts. I suggest people create feedbacks for Apple to support retrieving a `UIFont` or `NSFont` instance from `Font` directly. – David James Dec 26 '20 at 08:32
  • 2
    @Luke_Howard perhaps change the method name to `preferredFont(from font:Font)` to reflect that this only returns default system font. – David James Dec 26 '20 at 08:45
  • I don't think that this answers the OP's question. There's the assumption of using the default font. What if the OP loaded a custom font? – RobMac Nov 19 '22 at 17:47
9

Here is a reformatting of Luke Howard's solution to reduce the amount of text

extension UIFont {
  class func preferredFont(from font: Font) -> UIFont {
      let style: UIFont.TextStyle
      switch font {
        case .largeTitle:  style = .largeTitle
        case .title:       style = .title1
        case .title2:      style = .title2
        case .title3:      style = .title3
        case .headline:    style = .headline
        case .subheadline: style = .subheadline
        case .callout:     style = .callout
        case .caption:     style = .caption1
        case .caption2:    style = .caption2
        case .footnote:    style = .footnote
        case .body: fallthrough
        default:           style = .body
     }
     return  UIFont.preferredFont(forTextStyle: style)
   }
}
MarkAurelius
  • 1,203
  • 1
  • 14
  • 27
2

No you can't, you have to use the params you passed to the Font to create UIFont

JIE WANG
  • 1,875
  • 1
  • 17
  • 27