NSAttributedString,更改字体总体,但保留所有其他属性吗?
收藏

Say I have an NSMutableAttributedString .

在整个字符串中,字符串具有多种格式组合:

这是一个例子:

这个字符串在iOS中很难改变,真的很烂。

但是,字体本身不是您想要的字体。

我想要:

对于每个字符,将该字符更改为特定字体(例如Avenir)

但,

对于每个角色,请保留先前在该角色上使用的其他所有属性(粗体,斜体,颜色等)。

你到底是怎么做到的?

注意:

如果您在整个范围内琐碎地添加属性“ Avenir”:它只是删除所有其他属性范围,则会丢失所有格式。不幸的是,属性实际上不是“加法”。

最佳答案

Since rmaddy's answer did not work for me (f.fontDescriptor.withFace(font.fontName) does not keep traits like bold), here is an updated Swift 4 version that also includes color updating:

extension NSMutableAttributedString {
    func setFontFace(font: UIFont, color: UIColor? = nil) {
        beginEditing()
        self.enumerateAttribute(
            .font, 
            in: NSRange(location: 0, length: self.length)
        ) { (value, range, stop) in

            if let f = value as? UIFont, 
              let newFontDescriptor = f.fontDescriptor
                .withFamily(font.familyName)
                .withSymbolicTraits(f.fontDescriptor.symbolicTraits) {

                let newFont = UIFont(
                    descriptor: newFontDescriptor, 
                    size: font.pointSize
                )
                removeAttribute(.font, range: range)
                addAttribute(.font, value: newFont, range: range)
                if let color = color {
                    removeAttribute(
                        .foregroundColor, 
                        range: range
                    )
                    addAttribute(
                        .foregroundColor, 
                        value: color, 
                        range: range
                    )
                }
            }
        }
        endEditing()
    }
}

笔记

The problem with f.fontDescriptor.withFace(font.fontName) is that it removes symbolic traits like italic, bold or compressed, since it will for some reason override those with default traits of that font face. Why this is so totally eludes me, it might even be an oversight on Apple's part; or it's "not a bug, but a feature", because we get the new font's traits for free.

So what we have to do is create a font descriptor that has the symbolic traits from the original font's font descriptor: .withSymbolicTraits(f.fontDescriptor.symbolicTraits). Props to rmaddy for the initial code on which I iterated.

I've already shipped this in a production app where we parse a HTML string via NSAttributedString.DocumentType.html and then change the font and color via the extension above. No problems so far.

    公众号
    关注公众号订阅更多技术干货!