NSAttributedString,整体更改字体但保留所有其他属性? [英] NSAttributedString, change the font overall BUT keep all other attributes?

查看:55
本文介绍了NSAttributedString,整体更改字体但保留所有其他属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 NSMutableAttributedString .

该字符串具有多种混合格式:

The string has a varied mix of formatting throughout:

这是一个例子:

这个字符串改变在iOS中,它真的糟糕.

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

However, the font per se is not the font you want.

我想:

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

for each and every character, change that character to a specific font (say, Avenir)

对于每个字符,保持其他属性的混合(粗体、斜体、颜色等)以前在那个角色上就位.

for each and every character, keep the mix of other attributions (bold, italic, colors, etc etc) which was previously in place on that character.

你到底是怎么做到的?

注意:

如果你随便添加一个属性Avenir"在整个范围内:它只是删除所有其他属性范围,您会丢失所有格式.不幸的是,属性不是,实际上是可加的".

if you trivially add an attribute "Avenir" over the whole range: it simply deletes all the other attribute ranges, you lose all formatting. Unfortunately, attributes are not, in fact "additive".

推荐答案

因为 rmaddy 的回答对我不起作用(f.fontDescriptor.withFace(font.fontName) 不保留粗体等特征),这是一个更新的 Swift 4 版本,其中还包括颜色更新:

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()
    }
}

<小时>

注意事项

f.fontDescriptor.withFace(font.fontName) 的问题在于它删除了诸如 italicboldcompressed,因为它会由于某种原因覆盖那些具有该字体默认特征的字体.为什么我完全无法理解这一点,这甚至可能是 Apple 的疏忽;或者它不是错误,而是功能",因为我们免费获得新字体的特征.


Notes

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.

所以我们要做的是创建一个字体描述符,它具有来自原始字体的字体描述符的符号特征:.withSymbolicTraits(f.fontDescriptor.symbolicTraits).为我迭代的初始代码提供 rmaddy 的道具.

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.

我已经在一个生产应用程序中发布了这个,我们通过 NSAttributedString.DocumentType.html 解析了一个 HTML 字符串,然后通过上面的扩展更改字体和颜色.目前没有问题.

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.

这篇关于NSAttributedString,整体更改字体但保留所有其他属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆