首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不能子类UIFont

不能子类UIFont
EN

Stack Overflow用户
提问于 2022-07-13 21:43:36
回答 1查看 50关注 0票数 1

我在iOS应用程序中使用自定义字体,并设置了如下所示的字体:

代码语言:javascript
复制
private enum MalloryProWeight: String {
 case book = "MalloryMPCompact-Book"
 case medium = "MalloryMPCompact-Medium"
 case bold = "MalloryMPCompact-Bold"}


extension UIFont {
enum Caption {
    private static var bookFont: UIFont {
        UIFont(name: MalloryProWeight.book.rawValue, size: 1)!
    }

    private static var mediumFont: UIFont {
        UIFont(name: MalloryProWeight.medium.rawValue, size: 1)!
    }

    private static var boldFont: UIFont {
        UIFont(name: MalloryProWeight.bold.rawValue, size: 1)!
    }

    static var book: UIFont {
        return bookFont.withSize(10)
    }

    static var medium: UIFont {
        mediumFont.withSize(10)
    }

    static var bold: UIFont {
        boldFont.withSize(10)
    }
}

因此,在呼叫站点,我可以做以下工作:

代码语言:javascript
复制
UIFont.Caption.bold

这很好用,我有一个NSAttributed扩展。UIFont和颜色,并返回属性字符串=,因此它们都很适合。

但是,我现在需要在我的每个字体上设置LetterSpacing和LineHeight。

我不想更新NSAttributed扩展以接受这些值来设置它们--理想情况下,我希望可以从UIFont访问它们

因此,我尝试将UIFont子类添加到它中-如下所示:

代码语言:javascript
复制
class MrDMyCustomFontFont: UIFont {
    var letterSpacing: Double?
}

然后像这样使用它

代码语言:javascript
复制
private static var boldFont: UIFont {
    MrDMyCustomFontFont(name: MalloryProWeight.bold.rawValue, size: 1)!
}

但是,编译器会抱怨,我不知道如何解决它:

传递给不带参数的调用的

参数

我的问题有两部分:

  1. 如何在UIFont
  2. 上添加自己的自定义属性(并在每个实例的基础上设置),否则如何正确地子类UIFont以便在那里添加自己的属性?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-13 22:59:35

不能子类UIFont,因为它是通过UICTFont桥接到CTFont的。这就是为什么init方法在标头中被标记为“未继承”的原因。这不是一门普通的课。

您可以轻松地向UIFont添加一个新属性,但它不会按照您希望的方式工作。这正是你所要求的:每个实例。但是它不会被复制,因此从boldFont.withSize(10)返回的实例将不具有与boldFont相同的值。如果您想要代码,您可以这样做:

代码语言:javascript
复制
private var letterSpacingKey: String? = nil

extension UIFont {
    var letterSpacing: Double? {
        get {
            (objc_getAssociatedObject(self, &letterSpacingKey) as? NSNumber)?.doubleValue
        }
        set {
            objc_setAssociatedObject(self, &letterSpacingKey, newValue.map(NSNumber.init(value:)),
                                     .OBJC_ASSOCIATION_RETAIN)
        }
    }
}

然后你可以设置它:

代码语言:javascript
复制
let font = UIFont.boldSystemFont(ofSize: 1)
font.letterSpacing = 1
print(font.letterSpacing) // Optional(1)

但是,只要创建了派生字体,您就会丢失它:

代码语言:javascript
复制
let newFont = font.withSize(10)
print(newFont.letterSpacing) // nil

所以我觉得你不想那样。

但这其中的大部分都没什么意义。你会怎么处理这些财产?“字母间距”不是字体特征,而是布局/样式特征。在字体的高度度量上撒谎也可能是一个错误的工具;配置它通常也是一个段落特性。

您可能想要的是一种“样式”,它可以跟踪所有问题的内容(字体、间距、段落样式等),并且可以应用于AttributedString。幸运的是,这已经存在于iOS 15+:AttributeContainer中。在iOS 15之前,您可以只使用[NSAttributedString.Key: Any]

然后,您可以直接合并容器/字典,而不是(NS)AttributedString扩展来合并您的字体(这正是它设计的工作方式)。

代码语言:javascript
复制
extension AttributeContainer {
    enum Caption {

        private static var boldAttributes: AttributeContainer {
            var container = AttributeContainer()
            container.font = UIFont(name: MalloryProWeight.bold.rawValue, size: 1)!
            container.expansion = 1
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.lineSpacing = 1.5
            container.paragraphStyle = paragraphStyle
            return container
        }

        static var bold: AttributeContainer {
            var attributes = boldAttributes
            attributes.font = boldAttributes.font.withsize(10)
            return attributes
        }
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72972953

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档