获取swift中的字体属性 4

Get font attributes in swift 4

我已将项目从 swift 3 迁移到 swift 4,但找不到如何从 UIFontDescriptor 获取字体属性的信息。这是在 swift 3 中完美运行的代码:

 @objc convenience init(myCoder aDecoder: NSCoder) {
        if let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor {
            if let fontAttribute = fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String {
                var fontName = ""
                switch fontAttribute {
                case "CTFontRegularUsage":
                    fontName = Roboto.regular.rawValue
                case "CTFontEmphasizedUsage", "CTFontBoldUsage":
                    fontName = Roboto.bold.rawValue
                default:
                    fontName = Roboto.regular.rawValue
                }
                self.init(name: fontName, size: fontDescriptor.pointSize)!
            }
            else {
                self.init(myCoder: aDecoder)
            }
        }
        else {
            self.init(myCoder: aDecoder)
        }
    }

但在 swift 4 行中:

if let fontAttribute = fontDescriptor.fontAttributes["NSCTFontUIUsageAttribute"] as? String

有一个错误:Ambiguous reference to member 'subscript'。 有什么想法可以更改吗?

谢谢!

let font: UIFont

let fontAttribute = UIFontDescriptor.AttributeName("NSCTFontUIUsageAttribute")

let fontUsageAttribute = font.fontDescriptor.fontAttributes[fontAttribute] as? String

您似乎正试图将自定义字体视为动态类型字体。在 iOS 11 中支持的方法是使用 UIFontMetrics.

这是我的解决方案。为我工作

 @objc convenience init(myCoder aDecoder: NSCoder) {
    if let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor {

           let fontAttribute = UIFontDescriptor.AttributeName("NSCTFontUIUsageAttribute")  
        if let fontAttribute = fontDescriptor.fontAttributes[fontAttribute] as? String {

           var fontName = ""
            switch fontAttribute {
            case "CTFontRegularUsage":
                fontName = Roboto.regular.rawValue
            case "CTFontEmphasizedUsage", "CTFontBoldUsage":
                fontName = Roboto.bold.rawValue
            default:
                fontName = Roboto.regular.rawValue
            }
            self.init(name: fontName, size: fontDescriptor.pointSize)!
        }
        else {
            self.init(myCoder: aDecoder)
        }
    }
    else {
        self.init(myCoder: aDecoder)
    }
}

1) 确保您所有的项目/目标构建设置显示 Swift 语言版本 4.x(目前为 4.0)。没有这个设置,新的 UIFontDescriptor 值将不可用。注意:具有多个目标的项目可能会出现异常,具体取决于您选择的目标以及为该目标指定的 Swift 版本。为避免,请确保所有目标都更新为 Swift 4.0.

2) 使用内置静态类型访问特定的 UIFontAttribute,注意预期的 return 类型。

对于带有可选 NSString return 的 UIFontAttribute,类型:

let fontAttribute = fontDescriptor.object(forKey: .face) as? String

或者在您的示例中,不存在内置静态类型:

let fontAttribute = fontDescriptor.object(forKey: UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")) as? String

这对我有用,为 NSCTFontUIUsageAttribute 创建一个静态值 nsctFontUIUsage,然后在 fontDescriptor.fontAttributes[.nsctFontUIUsage]:

中使用它
extension UIFontDescriptor.AttributeName {
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}

extension UIFont {
    @objc convenience init(myCoder aDecoder: NSCoder) {
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
                self.init(myCoder: aDecoder)
                return
        }
        var fontName = ""
        switch fontAttribute {

        case "CTFontRegularUsage":
            fontName = Resources.Fonts.Weight.regular

        case "CTFontEmphasizedUsage", "CTFontBoldUsage":
            fontName = Resources.Fonts.Weight.semibold

        case "CTFontObliqueUsage":
            fontName = Resources.Fonts.Weight.italic

        default:
            fontName = Resources.Fonts.Weight.light
        }
        self.init(name: fontName, size: fontDescriptor.pointSize)!
    }
}