无法在 iOS 13 上创建小型大写字母选择器

Cannot create Small Caps Selector on iOS 13

下面的代码使我能够在 iOS 12 上创建小型大写字母文本。但是在 iOS 13 上它停止工作了。

iOS 12 日志

.SFUIDisplay-Semibold
.SFUIDisplay-Semibold

iOS 13 日志

.SFUI-Semibold
TimesNewRomanPSMT

似乎 SFUI 字体至少在 iOS 13 中更改了名称,但是否也放弃了对小型大写字母的支持?

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)

像这样的系统字体现在不再可以使用 'dot' / . 符号进行引用(即使像您的 font.fontName 示例一样重新创建它们)按照:

https://developer.apple.com/videos/play/wwdc2019/227/

从 iOS 13 开始,您可以使用新枚举 UIFontDescriptor.SystemDesign,使用 regularroundedserifmonospaced .

如何使用 Swift 中的描述符创建字体的示例(查看我如何使用 design 参数):

extension UIFont {

    convenience init?(
        style: UIFont.TextStyle,
        weight: UIFont.Weight = .regular,
        design: UIFontDescriptor.SystemDesign = .default) {

        guard let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: style)
            .addingAttributes([UIFontDescriptor.AttributeName.traits: [UIFontDescriptor.TraitKey.weight: weight]])
            .withDesign(design) else {
                return nil
        }
        self.init(descriptor: descriptor, size: 0)
    }
}

从@Ash Camerons 的回答中汲取灵感,这是更新后的代码,可让您应用小型大写字母

请注意,这仅适用于 iOS 13+,但您可以选择为 iOS 13 及更高版本添加 .withDesign(systemDesign) 行。

let pointSize: CGFloat = 20
let weight: UIFont.Weight = .semibold
let systemDesign: UIFontDescriptor.SystemDesign = .default

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

let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .callout)
        .addingAttributes([UIFontDescriptor.AttributeName.traits: [UIFontDescriptor.TraitKey.weight: weight]])
        .addingAttributes([UIFontDescriptor.AttributeName.featureSettings: settings])
        .addingAttributes([UIFontDescriptor.AttributeName.size: pointSize])
        .withDesign(systemDesign)

let font = UIFont(descriptor: descriptor!, size: pointSize)

您的代码总是错误的。您首先创建一种字体,然后通过传递字体的 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)

那是永远不会正确的。您应该直接从 字体本身 派生字体描述符。这就是您的代码应该总是 的样子。它在 iOS 12 时有效,现在有效:

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)