ios 如何将动态缩放的UIFont转换回原始UIFont?

mkh04yzy  于 2023-06-25  发布在  iOS
关注(0)|答案(1)|浏览(115)

我正在开发一个文本编辑器应用程序,其中涉及NSAttributedString的编码和解码。我正在使用UITextView来显示和编辑文本。我使用NSKeyedArchiver使NSAttributedString可编码。

class AttributedStringCodable : Codable {

    var attributedString : NSAttributedString

    init(nsAttributedString : NSAttributedString) {
        self.attributedString = nsAttributedString
    }

    public required init(from decoder: Decoder) throws {
        let singleContainer = try decoder.singleValueContainer()
        guard let attributedString = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(singleContainer.decode(Data.self)) as? NSAttributedString else {
            throw DecodingError.dataCorruptedError(in: singleContainer, debugDescription: "Data is corrupted")
        }
        self.attributedString = attributedString
    }

    public func encode(to encoder: Encoder) throws {
        var singleContainer = encoder.singleValueContainer()
        try singleContainer.encode(NSKeyedArchiver.archivedData(withRootObject: attributedString, requiringSecureCoding: false))
    }
}

我想在我的应用程序中支持动态类型字体。因此,当用户从设置中增加字体大小时,我的属性字符串会变大。问题是当我保存(编码)NSAttributedString时,它会和动态缩放的字体沿着保存。因此,下次当我打开应用并加载(解码)带有一些不同动态文本设置的属性文本时,应用程序崩溃,并给出以下消息:“UIFontMetrics返回的缩放字体不应用于创建另一个缩放字体。我知道发生这种情况是因为我试图从一个已经缩放的字体创建另一个缩放的字体。所以我想在保存(编码)属性字符串之前回到原始字体。例如

let originalFont = UIFont.systemFont(ofSize: 24, weight: .bold)

let traitCollection = UITraitCollection(preferredContentSizeCategory: .accessibilityLarge)
let dynamicFont = UIFontMetrics.default.scaledFont(for: originalFont, compatibleWith: traitCollection)

print(originalFont.pointSize)
print(dynamicFont.pointSize)

现在我如何将dynamicFont转换回originalFont?有没有其他的方法来实现我想要的?

rdrgkggo

rdrgkggo1#

因此,我的方法是将originalFont与traitCollection配对在一个可以解码和编码的缓存数组中。一开始看起来很简单,但记住你不能解码UIFont & UIContentSizeCategory。这可能不是最好的方法,但你去吧。

struct CustomFontHolder: Decodable {
    
    var id: String
    let originalSize: CGFloat
    let originalWeight: CustomFontWeight
    let traitCollection: ContentSizeCategory
    
    var originalFont: UIFont {
        return UIFont.systemFont(ofSize: originalSize, weight: originalWeight.systemFontWeight)
    }
    
    var dynamicFont: UIFont {
        return UIFontMetrics.default.scaledFont(
            for: originalFont,
            compatibleWith: UITraitCollection(preferredContentSizeCategory: traitCollection.category)
        )
    }
}

enum CustomFontWeight: Decodable {
    case ultraLight
    case thin
    case light
    case regular
    case medium
    case semibold
    case bold
    case heavy
    case black
    
    var systemFontWeight: UIFont.Weight {
        switch self {
        case .ultraLight: return .ultraLight
        case .thin: return .thin
        case .light: return .light
        case .regular: return .regular
        case .medium: return .medium
        case .semibold: return .semibold
        case .bold: return .bold
        case .heavy: return .heavy
        case .black: return .black
        }
    }
}

public enum ContentSizeCategory: Decodable {
    case unspecified
    case extraSmall
    case small
    case medium
    case large
    case extraLarge
    case extraExtraLarge
    case extraExtraExtraLarge
    case accessibilityMedium
    case accessibilityLarge
    case accessibilityExtraLarge
    case accessibilityExtraExtraLarge
    case accessibilityExtraExtraExtraLarge
    
    
    var category: UIContentSizeCategory {
        switch self {
        case .unspecified: return .unspecified
        case .extraSmall: return .extraSmall
        case .small: return .small
        case .medium: return .medium
        case .large: return .large
        case .extraLarge: return .extraLarge
        case .extraExtraLarge: return .extraExtraLarge
        case .extraExtraExtraLarge: return .extraExtraExtraLarge
        case .accessibilityMedium: return .accessibilityMedium
        case .accessibilityLarge: return .accessibilityLarge
        case .accessibilityExtraLarge: return .accessibilityExtraLarge
        case .accessibilityExtraExtraLarge: return .accessibilityExtraExtraLarge
        case .accessibilityExtraExtraExtraLarge: return .accessibilityExtraExtraExtraLarge
        }
    }
}

enum FontKeys: String {
    case homeTitleFont = "HomeTitleFont"
}

var CustomFontHolderCache: [CustomFontHolder] = []

CustomFontHolderCache.append(
    CustomFontHolder(
        id: FontKeys.homeTitleFont.rawValue,
        originalSize: 24,
        originalWeight: .bold,
        traitCollection: .accessibilityLarge
    )
)

var fontHolder = CustomFontHolderCache.first(where: { $0.id == FontKeys.homeTitleFont.rawValue })!

var dynamicFont = fontHolder.dynamicFont
var originalFont = fontHolder.originalFont

相关问题