Search code examples
iosswiftxcodeios13ios12

Cannot create Small Caps Selector on iOS 13


This code below enabled me to create small caps text on iOS 12. However on iOS 13 it's stopped working.

iOS 12 log

.SFUIDisplay-Semibold
.SFUIDisplay-Semibold

iOS 13 log

.SFUI-Semibold
TimesNewRomanPSMT

It seems that the SFUI font has changed name at least in iOS 13, but has it also dropped support for small caps?

let font = UIFont.systemFont(ofSize: 20, weight: .semibold)
print(font.fontName)

let settings = [[UIFontDescriptor.FeatureKey.featureIdentifier: kLowerCaseType,
                 UIFontDescriptor.FeatureKey.typeIdentifier: kLowerCaseSmallCapsSelector]]

let attributes: [UIFontDescriptor.AttributeName: AnyObject] = [UIFontDescriptor.AttributeName.featureSettings: settings as AnyObject,
                                                               UIFontDescriptor.AttributeName.name: font.fontName as AnyObject]

let smallCapsFont = UIFont(descriptor: UIFontDescriptor(fontAttributes: attributes), size: 20)
print(smallCapsFont.fontName)

Solution

  • Your code was always wrong. You start by creating a font and then you derive a font descriptor from it by passing through the font's name:

    let font = UIFont.systemFont(ofSize: 20, weight: .semibold)
    let settings = [
        [UIFontDescriptor.FeatureKey.featureIdentifier: kLowerCaseType,
        UIFontDescriptor.FeatureKey.typeIdentifier: kLowerCaseSmallCapsSelector]
    ]
    let attributes: [UIFontDescriptor.AttributeName: AnyObject] = [
        UIFontDescriptor.AttributeName.featureSettings: settings as AnyObject,
        UIFontDescriptor.AttributeName.name: font.fontName as AnyObject // ** NO!
    ]
    let smallCapsFont = UIFont(descriptor: UIFontDescriptor(fontAttributes: attributes), size: 20)
    

    That was never correct. You should derive the font descriptor directly from the font itself. This is what your code should always have looked like. It worked in iOS 12 and it works now:

    let font = UIFont.systemFont(ofSize: 20, weight: .semibold)
    let settings = [
        [UIFontDescriptor.FeatureKey.featureIdentifier: kLowerCaseType,
        UIFontDescriptor.FeatureKey.typeIdentifier: kLowerCaseSmallCapsSelector]
    ]
    let desc = font.fontDescriptor.addingAttributes([.featureSettings:settings])
    let smallCapsFont = UIFont(descriptor: desc, size: 0)