What Is a Monospace Font in iOS

What is a monospace font in iOS?

Looking at an old listing of fonts shipped with iOS I see several one monospace fonts.

(eg. Andale Mono, Monaco, Courier New)


For 2018 it's only Menlo and Courier.

Using -apple-system for monospace and serif

Starting from Safari 13.1, they added font family names for system fonts:

  • ui-monospace — SF Mono
  • ui-serif — New York
  • ui-sans-serif — San Francisco (same as system-ui and -apple-system)

See the blog post.

The CSS I use to get the system monospace on most platforms is as follows:

code {
font-family: 'SF Mono', SFMono-Regular, ui-monospace,
'DejaVu Sans Mono', Menlo, Consolas, monospace;
}

The first three are SF Mono, then the Bitstream Vera-derived fonts on Linux (DejaVu) and Mac (Menlo), closing with whatever works on Windows (Consolas).

How do I get a monospace font that respects acessibility settings

Here is an extension to UIFontDescriptor that returns a preferred monospaced font descriptor for a given text style. There is no simple way to get a fully monospaced font using UIFont or UIFontDescriptor. This solution attempts to find a good monospaced font and falls back to Courier if needed.

extension UIFontDescriptor {
static let monoDescriptor: UIFontDescriptor = {
// Attempt to find a good monospaced, non-bold, non-italic font
for family in UIFont.familyNames {
for name in UIFont.fontNames(forFamilyName: family) {
let f = UIFont(name: name, size: 12)!
let fd = f.fontDescriptor
let st = fd.symbolicTraits
if st.contains(.traitMonoSpace) && !st.contains(.traitBold) && !st.contains(.traitItalic) && !st.contains(.traitExpanded) && !st.contains(.traitCondensed) {
return fd
}
}
}

return UIFontDescriptor(name: "Courier", size: 0) // fallback
}()

class func preferredMonoFontDescriptor(withTextStyle style: UIFontTextStyle) -> UIFontDescriptor {
// Use the following line if you need a fully monospaced font
let monoDescriptor = UIFontDescriptor.monoDescriptor

// Use the following two lines if you only need monospaced digits in the font
//let monoDigitFont = UIFont.monospacedDigitSystemFont(ofSize: 0, weight: .regular)
//let monoDescriptor = monoDigitFont.fontDescriptor

// Get the non-monospaced preferred font
let defaultFontDescriptor = preferredFontDescriptor(withTextStyle: style)
// Remove any attributes that specify a font family or name and remove the usage
// This will leave other attributes such as size and weight, etc.
var fontAttrs = defaultFontDescriptor.fontAttributes
fontAttrs.removeValue(forKey: .family)
fontAttrs.removeValue(forKey: .name)
fontAttrs.removeValue(forKey: .init(rawValue: "NSCTFontUIUsageAttribute"))
let monospacedFontDescriptor = monoDescriptor.addingAttributes(fontAttrs)

return monospacedFontDescriptor.withSymbolicTraits(defaultFontDescriptor.symbolicTraits) ?? monospacedFontDescriptor
}
}

Note the comments about whether you need a font that is fully monospaced or a font that just has monospaced digits. Comment/Uncomment those lines to suit your specific needs.

Sample usage:

let bodyMonospacedFont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: .body), size: 0)
textview.font = bodyMonospacedFont

The following is some test code to confirm that the results of preferredMonoFontDescriptor(withTextStyle:) works properly for all styles:

let textStyles: [UIFontTextStyle] = [ .body, .callout, .caption1, .caption2, .footnote, .headline, .subheadline, .largeTitle, .title1, .title2, .title3 ]
for style in textStyles {
let nfont = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: style), size: 0)
let mfont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: style), size: 0)
print(style)
print(nfont)
print(mfont)
}

If you compare each pair of results, they have the same size, weight, and style, just a different font.

How to use the .monospaced system font design

It seems .monospaced font only applies when given a fixed size:

Text("monospaced")
.font(.system(size: 14, design: .monospaced))

This won't work given a dynamic text style such as body. But as you've also mentioned it works fine for other fonts so this is probably a bug in Xcode 11.0 beta and hopefully will be fixed in next releases.



Update:

This issue was fixed with Xcode 11 beta 3. The following code works now:

Text("monospaced")
.font(.system(.body, design: .monospaced))

Does iOS dev has build-in fixed width font?

Here's the list of built-in fonts available on iOS: http://iosfonts.com.

Courier looks like the only monospace font in there.



Related Topics



Leave a reply



Submit