Display proportionally spaced numbers (instead of monospaced / tabular) on iOS

I process numbers in iOS (targeting 7 and above), storing them in NSAttributedString and rendering using drawAtPoint :. I am using Helvetica Neue.

I noticed that the digits of numbers drawn in this way are not proportional - all glyphs have the same width. Even the skinny "1" takes the same place as the "0".

The test confirms this:

for(NSInteger i=0; i<10; ++i) { NSString *iString = [NSString stringWithFormat: @"%d", i]; const CGSize iSize = [iString sizeWithAttributes: [self attributes]]; NSLog(@"Size of %d is %f", i, iSize.width); } 

C, in another place:

 -(NSDictionary *) attributes { static NSDictionary * attributes; if(!attributes) { attributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:11], NSForegroundColorAttributeName: [UIColor whiteColor] }; } return attributes; } 

The resulting glyphs have the same width of 6.358 points.

Is there any rendering option that I can enable to include proportional characters ? Is there another font (ideally similar to Helvetica Neue) that supports proportional digital characters (ideally, embedded)? Anything else?

Thanks.

+7
ios nsstring uifont uifontdescriptor
source share
1 answer

iOS 7 allows you to specify fonts using instances of UIFontDescriptor . Then the UIFont instance UIFont obtained from the descriptor.

When specifying a UIFontDescriptor , you can also get its setting, which changes some characteristics using the [fontDescriptor fontDescriptorByAddingAttributes: attibutes] , where attributes is an NSDictionary of font attributes.

Apple documents attributes in a UIFontDescriptor link .

From the link, one specific font descriptor attribute UIFontDescriptorFeatureSettingsAttribute allows you to provide "An array of dictionaries representing the non-standard functions of the font of the font. Each dictionary contains a UIFontFeatureTypeIdentifierKey and UIFontFeatureSelectorIdentifierKey ."

The UIFontFeatureTypeIdentifierKey and UIFontFeatureSelectorIdentifierKey documentation is located in the Apple Font Registry file documentation . A specific case of proportional numbers is described in this pdf slide of Apple's presentation , so I just shot it.

This code will take an existing UIFont instance and return you a new instance with proportional digits:

 // You'll need this somewhere at the top of your file to pull // in the required constants. #import <CoreText/CoreText.h> … UIFont *const existingFont = [UIFont preferredFontForTextStyle: UIFontTextStyleBody]; UIFontDescriptor *const existingDescriptor = [existingFont fontDescriptor]; NSDictionary *const fontAttributes = @{ // Here comes that array of dictionaries each containing UIFontFeatureTypeIdentifierKey // and UIFontFeatureSelectorIdentifierKey that the reference mentions. UIFontDescriptorFeatureSettingsAttribute: @[ @{ UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType), UIFontFeatureSelectorIdentifierKey: @(kProportionalNumbersSelector) }] }; UIFontDescriptor *const proportionalDescriptor = [existingDescriptor fontDescriptorByAddingAttributes: fontAttributes]; UIFont *const proportionalFont = [UIFont fontWithDescriptor: proportionalDescriptor size: [existingFont pointSize]]; 

You can add this as a category on UIFont if you want, etc.

Edit note: thanks to Chris Schwerdt for improvement.

+17
source share

All Articles