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 Monoui-serif
— New Yorkui-sans-serif
— San Francisco (same assystem-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
How to Generate a Barcode from a String in Swift
How to Mimic Keyboard Animation on iOS 7 to Add "Done" Button to Numeric Keyboard
How to Put the Uipagecontrol Element on Top of the Sliding Pages Within a Uipageviewcontroller
Set Uitableview's Height to the Height of Its Content with Auto Layout
Xcode - Symbol(S) Not Found for Architecture X86_64 (iOS Lib)
Steps to Create and Edit a Plist File in Xcode
How to Open the Imagepicker in Swiftui
How to Figure Out Which Url Is Being Blocked by App Transport Security
Push Notifications Not Being Received on iOS 10, But Working on iOS 9 and Before
How to Retrieve Facebook Response Using Facebook iOS Sdk
Code Signing Is Required for Product Type Unit Test Bundle in Sdk iOS 8.0
iOS 7 and Later: Set Status Bar Style Per View Controller
Apn (Apple Push Notification) Payload Size Limit
An Error Occurred Uploading to the Itunes Store
What Is MACh-O Type Should I Use It in My iOS Objective-C Project
How to Find Out Distance Between Coordinates
Want to Create a Cool Static UI But:"Static Table Views Are Only Valid..."