更改特定 UIFont.TextStyle 的所有 UILabel

Change all UILabels for a specific UIFont.TextStyle

我在我的应用程序中使用 TextStyles 来支持动态字体。我面临着为每个 TextStyle 更改字体的挑战。因此,例如 TextStyle.body 应该是 MyAwesomeBODYFontTextStyle.headline 应该是 MyAwesomeHeadlineFont。这适用于整个应用程序。为整个应用程序设置字体将不起作用,因为我需要为不同的样式设置多种字体。

是否可以使用整个应用程序的自定义字体而不是分别为每个标签覆盖这些 TextStyles

我尝试了什么:

UILabelappearance 代理设置字体通常可以正常工作:

let labelAppearance = UILabel.appearance()
let fontMetrics = UIFontMetrics(forTextStyle: .body)
labelAppearance.font = fontMetrics.scaledFont(for: myAwesomeBodyFont)

但这会覆盖所有标签,无论它们使用什么 TextStyle

之后我尝试检查 TextStyle 但它因 UILabel.appearance().font 的 nil 指针异常而崩溃,或者甚至没有进入 if 块。

let labelAppearance = UILabel.appearance()
if let textStyle = labelAppearance.font.fontDescriptor.object(forKey: UIFontDescriptor.AttributeName.textStyle) as? UIFont.TextStyle {
    // this would be the place to check for the TextStyle and use the corresponding font

    let fontMetrics = UIFontMetrics(forTextStyle: textStyle)
    labelAppearance.font = fontMetrics.scaledFont(for: mayAwesomeBodyFont)
}

因为UILabel的外观没有font设置。

您不能直接 "set" 文本样式的自定义字体。 您可以获得文本样式的字体大小,然后可以使用自定义系列。

let systemDynamicFontDescriptor = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleBody)
let size = systemDynamicFontDescriptor.pointSize
let font = UIFont(name: MyAwesomeBODYFont, size: size)

对于iOS11+有scaledFont()

您可以将此字体变量设置为静态变量,这样就可以在应用程序的任何地方使用它。

您也可以查看此解决方案:

我最终创建了 UILabel 的子class,并让我所有的标签都继承自它。这样您就可以在 InterfaceBuilder and/or 中设置 class 在代码中创建自定义 class。

这是 DynamicCustomFontLabel class:

import UIKit

class DynamicCustomFontLabel: UILabel {

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!

        initCustomFont()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        initCustomFont()
    }

    private func initCustomFont() {
        if let textStyle = font.fontDescriptor.object(forKey: UIFontDescriptor.AttributeName.textStyle) as? UIFont.TextStyle {
            let fontMetrics = UIFontMetrics(forTextStyle: textStyle)
            var customFont: UIFont?

            switch textStyle {
            case .body:
                customFont = UIFont(name: "MyAwesomeBODYFont", size: 21)

            case .headline:
                customFont = UIFont(name: "MyAwesomeHeadlineFont", size: 48)

            // all other cases...

            default:
                return
            }

            guard let font = customFont else {
                fatalError("Failed to load a custom font! Make sure the font file is included in the project and the font is added to the Info.plist.")
            }

            self.font = fontMetrics.scaledFont(for: font)
        }
    }
}