How to get monospaced numbers in UILabel on iOS 9

前端 未结 8 1172
囚心锁ツ
囚心锁ツ 2020-12-13 06:52

At WWDC 2015, there was a session about the new “San Francisco” system font in iOS 9. It uses proportional number rendering instead of monospaced numbers by default when lin

相关标签:
8条回答
  • 2020-12-13 07:14

    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
                ]
            ]
        ]
    
    0 讨论(0)
  • 2020-12-13 07:15

    Example usage for Swift 5.2 following the accepted answer using dynamic type.

    label.font = .init(descriptor: UIFont.preferredFont(forTextStyle: .body)
                     .fontDescriptor.addingAttributes([
                     .featureSettings: [[
                         UIFontDescriptor.FeatureKey.featureIdentifier: kNumberSpacingType,
                                                    .typeIdentifier: kMonospacedNumbersSelector]]]),
                                                    size: 0)
    

    Worth mentioning for macOS (AppKit) it is slightly different:

    NSFont(descriptor: NSFont.systemFont(ofSize: 20).fontDescriptor
           .addingAttributes([.featureSettings: [[NSFontDescriptor.FeatureKey
           .selectorIdentifier: kMonospacedNumbersSelector,
           .typeIdentifier: kNumberSpacingType]]]), size: 0)
    
    0 讨论(0)
  • 2020-12-13 07:18

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

    0 讨论(0)
  • 2020-12-13 07:21

    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)
        }
    }
    
    0 讨论(0)
  • 2020-12-13 07:25

    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.

    0 讨论(0)
  • 2020-12-13 07:30

    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)
        }
    }
    
    0 讨论(0)
提交回复
热议问题