In an iOS project, I tried modifying the body font (UIFontTextStyleBody
) to include UIFontDescriptorTraitTightLeading
. When I read the fontAttributes
properties, it reports the NSFontNameAttribute
as .AppleSystemUIShortBody
(the original value is .AppleSystemUIBody
).
From this, I was able to figure out Apple's terms:
+------------+-----------------------------------+------------------------------+---------------------------------+
| Term | UIFontDescriptorSymbolicTraits | NSFontNameAttribute | NSCTFontUIUsageAttribute |
+------------+-----------------------------------+------------------------------+---------------------------------+
| | (none) | .AppleSystemUIBody | UICTFontTextStyleBody |
| Italic | UIFontDescriptorTraitItalic | .AppleSystemUIItalicBody | UICTFontTextStyleItalicBody |
| Emphasized | UIFontDescriptorTraitBold | .AppleSystemUIEmphasizedBody | UICTFontTextStyleEmphasizedBody |
| Short | UIFontDescriptorTraitTightLeading | .AppleSystemUIShortBody | UICTFontTextStyleShortBody |
| Tall? | UIFontDescriptorTraitLooseLeading | .AppleSystemUISpliceTallBody | UICTFontTextStyleTallBody |
+------------+-----------------------------------+------------------------------+---------------------------------+
If you attempt to do the same thing with UIFontDescriptorTraitExpanded
, UIFontDescriptorTraitCondensed
, UIFontDescriptorTraitVertical
, UIFontDescriptorTraitUIOptimized
, and then read the fontAttributes
, it returns the same value as the Body style. If you try the same thing with UIFontDescriptorTraitMonoSpace
, it returns a nil
dictionary.
Therefore, in an Apple Watch project, you should be able to use the Body Short Emphasized font like so:
/*1*/ UIFontDescriptor *fontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];
/*2*/ fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitTightLeading | UIFontDescriptorTraitBold];
/*3*/ UIFont *font = [UIFont fontWithDescriptor:fontDescriptor size:0];
/*4*/ [label setAttributedText:[[NSAttributedString alloc] initWithString:text attributes:@{NSFontAttributeName: font}]];
I say "should" because there are two bugs in play here:
- On line 2,
UIFontDescriptorTraitTightLeading
is being specified, yet this trait is ignored on both watch simulators. Bold and italic work just fine.
- On line 3, since
size
is set to 0
, it gets its value from the UIFontDescriptorSizeAttribute
in fontDescriptor
[1]. The problem is that on a 38mm device, there is a bug with both +[UIFontDescriptor preferredFontDescriptorWithTextStyle:]
and -[UIFont preferredFontForTextStyle:]
(used on line 1). When the user doesn't customize the font size, both methods return 16
, when clearly 15
should be chosen on the 38mm device. (You can verify this by placing a label on a storyboard, assigning it the Body size, and visually comparing it to a label that sets its size to 15 manually.)
Note: I am running Xcode 6.2.