How to get monospaced numbers in UILabel on iOS 9

℡╲_俬逩灬. 提交于 2019-11-28 17:52:32
Rudolf Adamkovič

Handy UIFont extension:

extension UIFont {
    var monospacedDigitFont: UIFont {
        let newFontDescriptor = fontDescriptor.monospacedDigitFontDescriptor
        return UIFont(descriptor: newFontDescriptor, size: 0)
    }
}

private extension UIFontDescriptor {
    var monospacedDigitFontDescriptor: UIFontDescriptor {
        let fontDescriptorFeatureSettings = [[UIFontDescriptor.FeatureKey.featureIdentifier: kNumberSpacingType,
                                              UIFontDescriptor.FeatureKey.typeIdentifier: kMonospacedNumbersSelector]]
        let fontDescriptorAttributes = [UIFontDescriptor.AttributeName.featureSettings: fontDescriptorFeatureSettings]
        let fontDescriptor = self.addingAttributes(fontDescriptorAttributes)
        return fontDescriptor
    }
}

Usage with @IBOutlet properties:

@IBOutlet private var timeLabel: UILabel? {
    didSet {
        timeLabel.font = timeLabel.font.monospacedDigitFont
    }
}

Latest version on GitHub.

This is now available in UIFont since iOS 9:

+ (UIFont *)monospacedDigitSystemFontOfSize:(CGFloat)fontSize weight:(CGFloat)weight NS_AVAILABLE_IOS(9_0);

eg:

[UIFont monospacedDigitSystemFontOfSize:42.0 weight:UIFontWeightMedium];

or in Swift:

UIFont.monospacedDigitSystemFont(ofSize: 42.0, weight: UIFontWeightMedium)

Accepted solution works great, but was crashing with compiler optimization set to Fast(default for Release builds). Rewrote the code like this and now it does not:

extension UIFont
{
    var monospacedDigitFont: UIFont
    {
        return UIFont(descriptor: fontDescriptor().fontDescriptorByAddingAttributes([UIFontDescriptorFeatureSettingsAttribute: [[UIFontFeatureTypeIdentifierKey: kNumberSpacingType, UIFontFeatureSelectorIdentifierKey: kMonospacedNumbersSelector]]]), size: 0)
    }
}

There has been quite some renaming in Swift 4, so the attributes now looks like this:

    let fontDescriptorAttributes = [
        UIFontDescriptor.AttributeName.featureSettings: [
            [
                UIFontDescriptor.FeatureKey.featureIdentifier: kNumberSpacingType,
                UIFontDescriptor.FeatureKey.typeIdentifier: kMonospacedNumbersSelector
            ]
        ]
    ]

Note: The method in the currently accepted answer has started crashing for me in Xcode 7.3 (Swift 2.2), only in Release builds. Eliminating the intermediary monospacedDigitFontDescriptor extension variable fixes the issue.

extension UIFont {
    var monospacedDigitFont: UIFont {
        let fontDescriptorFeatureSettings = [[UIFontFeatureTypeIdentifierKey: kNumberSpacingType, UIFontFeatureSelectorIdentifierKey: kMonospacedNumbersSelector]]
        let fontDescriptorAttributes = [UIFontDescriptorFeatureSettingsAttribute: fontDescriptorFeatureSettings]
        let oldFontDescriptor = fontDescriptor()
        let newFontDescriptor = oldFontDescriptor.fontDescriptorByAddingAttributes(fontDescriptorAttributes)

        return UIFont(descriptor: newFontDescriptor, size: 0)
    }
}

A bit improved version of the @Rudolf Adamkovic code which checks iOS version:

var monospacedDigitFont: UIFont {

    if #available(iOS 9, *) {
        let oldFontDescriptor = fontDescriptor()
        let newFontDescriptor = oldFontDescriptor.monospacedDigitFontDescriptor

        return UIFont(descriptor: newFontDescriptor, size: 0)
    } else {
       return self
    }
}

Or, just use Helvetica. It still has monospaced numbers and works retroactively to older iOS version.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!