Как остановить время UILabel от изменения размера при каждом приращении?

У меня есть функция секундомера в моем приложении, которая использует центрированный атрибут UILabel с пропорционально распределенным шрифтом для визуализации времени. При каждом приращении ширина метки меняется, создавая эффект подпрыгивания, который особенно плохо выглядит на быстрых скоростях. Вот пример .

Как я могу это исправить?

iOS 9 UPDATE

Теперь это однострочный:

UIFont.monospacedDigitSystemFontOfSize(17, weight: UIFontWeightRegular)

Кроме того, в прошлый раз, когда я попытался, решение, приведенное ниже, не работало для iOS 9. Довольно много времени отлаживалось, прежде чем наткнуться на это в заголовке.

Решение

Оказалось, что это тривиально с Text Kit в iOS 7.

Убедитесь, что основной текст импортирован:

#import <CoreText/CoreText.h>

Создайте параметр, который преобразует пропорциональные числа в моноширинный:

NSArray *monospacedSetting = @[@{UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType),
                                 UIFontFeatureSelectorIdentifierKey: @(kMonospacedNumbersSelector)}];

Создайте новый дескриптор шрифта, добавив текущий, используемый UILabel:

UIFontDescriptor *newDescriptor = [[timeLabel.font fontDescriptor] fontDescriptorByAddingAttributes:@{UIFontDescriptorFeatureSettingsAttribute: monospacedSetting}];

Обновить шрифт метки:

// Size 0 to use previously set font size
timeLabel.font = [UIFont fontWithDescriptor:newDescriptor size:0];

Ответ 1

Используйте моноширинный шрифт или параметры пропуска при создании шрифта, который заставляет моноширинные числа:

//kNumberSpacingType 6
//kMonospacedNumbersSelector 0
NSArray *setting = @[
                         @{
                             UIFontFeatureTypeIdentifierKey: @(6),
                             UIFontFeatureSelectorIdentifierKey: @(0)
                             }
                         ];

return [UIFont fontWithDescriptor:[[self fontDescriptor] fontDescriptorByAddingAttributes:@{UIFontDescriptorFeatureSettingsAttribute : setting}] size:0.0];

Ответ 2

Для будущих читателей:

Вот как включить моноширинные номера на iOS 9 с Сан-Франциско:

let originalFont = UIFont.systemFontOfSize(17)
let originalFontDescriptor = originalFont.fontDescriptor()

let fontDescriptorFeatureSettings = [
    [
    UIFontFeatureTypeIdentifierKey: kNumberSpacingType,
    UIFontFeatureSelectorIdentifierKey: kMonospacedNumbersSelector
    ]
]

let fontDescriptorAttributes = [UIFontDescriptorFeatureSettingsAttribute: fontDescriptorFeatureSettings]    
let fontDescriptor = originalFontDescriptor.fontDescriptorByAddingAttributes(fontDescriptorAttributes)
let font = UIFont(descriptor: fontDescriptor, size: 0)

Edit:

Также доступен на GitHub: https://github.com/salutis/swift-font-monospaced-digits