当 CTFeatureTypeIdentifier 不可用时如何使用 UIFontDescriptor

Giz*_*odo 3 xcode ios ctfont uifontdescriptor

我使用以下代码片段来获取字体功能:

let font = UIFont.systemFont(ofSize: 16)
let features: NSArray = CTFontCopyFeatures(font)!
print("properties = \(features)")
Run Code Online (Sandbox Code Playgroud)

所以如果我看到这个:

{
CTFeatureTypeExclusive = 1;
CTFeatureTypeIdentifier = 22;
CTFeatureTypeName = "Text Spacing";
CTFeatureTypeSelectors =         (
                {
        CTFeatureSelectorDefault = 1;
        CTFeatureSelectorIdentifier = 7;
        CTFeatureSelectorName = "No Change";
    },
                {
        CTFeatureSelectorIdentifier = 8;
        CTFeatureSelectorName = "No Kerning";
    }
);
Run Code Online (Sandbox Code Playgroud)

我可以将其翻译成 Swift:

 let fontDescriptorFeatureSettings = [
            [ UIFontDescriptor.FeatureKey.featureIdentifier : 22,
              UIFontDescriptor.FeatureKey.typeIdentifier : 8], ]
Run Code Online (Sandbox Code Playgroud)

这成功地为我禁用了字距调整。

在同一个片段中,我看到:

{
CTFeatureOpenTypeTag = cv05;
CTFeatureSampleText = I;
CTFeatureTooltipText = "\U00a9 2015-2022 Apple Inc. All rights reserved.";
CTFeatureTypeExclusive = 1;
CTFeatureTypeName = "Seriffed Capital I";
CTFeatureTypeSelectors =         (
                {
        CTFeatureOpenTypeValue = 0;
        CTFeatureSelectorDefault = 1;
        CTFeatureSelectorName = Off;
    },
                {
        CTFeatureOpenTypeValue = 1;
        CTFeatureSelectorName = On;
    }
);
Run Code Online (Sandbox Code Playgroud)

我如何将其翻译成 Swift 以获得衬线“I”?

对我来说,问题是缺少:

CT特征类型标识符

mat*_*att 6

首先,您的字距调整禁用代码在两个方面是错误的:

  • 在非常混乱的UIFontDescriptor.FeatureKey命名空间中,.featureIdentifier和已被弃用,分别由和.typeIdentifier代替。(我几年前就这些旧名称提交了一个错误,看起来苹果公司听到了我的意见并更改了它们。万岁!).type.selector

  • 对于与这些键对应的,如果不需要,请不要使用原始数字;这是难以辨认且脆弱的。这些事物通常有固定的名称。

所以当你说

let fontDescriptorFeatureSettings = [
    [ 
        UIFontDescriptor.FeatureKey.featureIdentifier: 22,
        UIFontDescriptor.FeatureKey.typeIdentifier: 8,
    ],
]
Run Code Online (Sandbox Code Playgroud)

你应该说

let fontDescriptorFeatureSettings = [
    [ 
        UIFontDescriptor.FeatureKey.type: kTextSpacingType,
        UIFontDescriptor.FeatureKey.selector: 8,
    ],
]
// I couldn't find a name for the `8` here
Run Code Online (Sandbox Code Playgroud)

可以,然后呢。要获得带衬线的 I,请将 指定kStylisticAltSixOnSelector为您的kStylisticAlternativesType.

let fontDescriptorFeatureSettings = [
    [ 
        UIFontDescriptor.FeatureKey.type: kStylisticAlternativesType,
        UIFontDescriptor.FeatureKey.selector: kStylisticAltSixOnSelector,
    ],
]
Run Code Online (Sandbox Code Playgroud)

现在,您可能会说,“好吧,好吧,但我还得到了一些我不一定想要的其他更改,例如弯曲的 ell 和斜线的零。”

确实如此,但在使用 UIFontDescriptor 进行操作的较高级别上,您对此无能为力。您在字典中找到的是单独的字形变体。您访问这些内容的唯一方法是直接使用 CoreText 绘制文本,我认为您不会想要达到该级别的文本绘制。您想要做的只是将此文本弹出到 UILabel 或类似的文本中,然后就可以完成它了;在这种情况下,打开替代六变体是最好的选择。

  • 我相信你会发现我的回答已经预料到了这个问题并且已经做出了回应。 (2认同)