源码

NSAttributedString 应用案例

常规Swift字符串对于存储纯文本来说已经足够,但如果你需要格式,图片,或者互动时,就要用到NSAttributedString。它是一个基础多合一字符串处理类,在iOS的很多地方都会用到,还经常和UILabel 与UITextView(它们都能直接接收属性字符串(attributed string))共同使用。

本文中我会给出一些NSAttributedString案例,展示NSAttributedString的功能,包括:手动创建字符串,添加列举属性,添加链接和图片等等。所有示例代码都可以在Swift playground上使用。因为Xcode可以预览字符串的样子,它很适合实验我们的属性字符串。

创建属性字符串(attributed string)

让我们从最基础的属性字符串开始:带有常规字符串,没有特别格式。

let quote = "Haters gonna hate"
let attributedQuote = NSAttributedString(string: quote)

 

在playground运行时,点击attributedQuote的预览键,就可以预览它了。因为还没有应用任何格式,它看起来就和普通字符串一样。

如果换成下面的:

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

我们要求文本渲染成72号大小,预览中也会看起来更大

字符串的样子会受到添加属性的影响,比如下例,文本就会被变成红色:

let font = UIFont.systemFont(ofSize: 72)
let attributes: [NSAttributedStringKey: Any] = [
    .font: font,
    .foregroundColor: UIColor.red,
]

而下面的代码会让文本变成白色,并有红色的光效

let font = UIFont.systemFont(ofSize: 72)
let shadow = NSShadow()
shadow.shadowColor = UIColor.red
shadow.shadowBlurRadius = 5

let attributes: [NSAttributedStringKey: Any] = [
    .font: font,
    .foregroundColor: UIColor.white,
    .shadow: shadow
]

如果你想进行段落设置,比如文本对齐,首行缩进,行距等等,需要用到一个独立的类型——NSMutableParagraphStyle。下面就是应用了段落格式,让文本居中,并且每段的首行缩进5点。

let font = UIFont.systemFont(ofSize: 72)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
paragraphStyle.firstLineHeadIndent = 5.0

let attributes: [NSAttributedStringKey: Any] = [
    .font: font,
    .foregroundColor: UIColor.blue,
    .paragraphStyle: paragraphStyle
]

let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

修改已存在的属性字符串

之前提到的都是从头开始创建一个属性字符串,但有时我们只是想修改一个已存在的。比如想把部分文本加粗。

那么还是从我们的基础字符串开始:

let quote = "Haters gonna hate"
let attributedQuote = NSMutableAttributedString(string: quote)

注意现在用到了NSMutableAttributedString,它是一个可以修改的属性字符串。由于类的特性,即使用let声明为常量,我们依旧可以修改这个对象。

如果你想让“gonna”变为红色,需要对这个属性字符串使用addAttribute()方法:

attributedQuote.addAttribute(.foregroundColorvalueUIColor.redrangeNSRange(location: 7, length: 5))

上例还用到了NSRange指定了字符串范围,这一项是必须要有的。

如果你想同时添加多属性,则要使用addAttributes,它使用和之前一样的字典法。下例中就对“Haters”一词应用了绿背景色和10点的字母间距。

let attributes: [NSAttributedStringKey: Any] = [.backgroundColor: UIColor.green, NSAttributedStringKey.kern: 10]
attributedQuote.addAttributes(attributes, range: NSRange(location: 0, length: 6))

虽然这个方法简单又高效,但我还是觉得创建多个独立属性字符串再合并到一起的方法更实用。尽管我的方法有点慢,占用内存更多,不过对于复杂字符串设计很好用。

完整的代码就是这样的:

let quote = "Haters gonna hate"

let firstAttributes: [NSAttributedStringKey: Any] = [.backgroundColor: UIColor.green, NSAttributedStringKey.kern: 10]
let secondAttributes = [NSAttributedStringKey.foregroundColor: UIColor.red]

let firstString = NSMutableAttributedString(string"Haters ", attributes: firstAttributes)
let secondString = NSAttributedString(string"gonna ", attributes: secondAttributes)
let thirdString = NSAttributedString(string"hate")

firstString.append(secondString)
firstString.append(thirdString)

 

这种方法把工作分成了简单的小块,这意味着我可以通过搭配混合不同函数构成新的属性字符串。

从HTML加载属性字符串

通过iOS对一些HTML进行语法分析也可以创建属性字符串。尽管只能支持一部分类型,但对于处理字体字号或者颜色来说已经足够了。

比如我们可以定义HTML使用内联CSS,让一个段落变成蓝色:

let html = """


This is blue!




"""

之后把它转化成数据实例,这样就可以读取为属性字符串了,

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

0

最后,可以把这个数据加载到一个NSAttributedString,并告知它我们在使用HTML的文件类型。

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

1

 

属性枚举

如果你有一个别人制作的属性字符串——比如从PDFView读取页面文本——你可以遍历所有的属性,并分析出它们在哪,包含了什么。

比如下面代码创建了一个字符串“the cat sat on the mat”,其中第1,3,5个单词比其他的大一些。

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

2

我们可以全部枚举这个字符串的字体属性,检查是否有加粗或变为红色的片段。通过enumerateAttribute()就可以做到这些,它会找出你请求的所有属性实例,一个个的传递给你,并附有它们的范围。此外还有一个停止选项,如果设为true,则循环停止。

代码如下:

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

3

还有更普遍的enumerateAttributes()方法,可以告诉人一个特定范围的所有属性。

把一张图放入属性字符串

目前为止,你可能觉得属性字符串看上去很简单,那就让我们把一张图片添加入一个属性字符串右边吧。这在app项目中很有用,这样就能更容易的加载图像文件了。

首先,创建一个常规的可变属性字符串

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

4

第二,创建一个NSTextAttachment实例,这个类特别用于给属性字符串附加图像。

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

5

第三,把这个附加图像放到它自己的属性字符串中,这样接下来就可以把它附到之前的字符串上了。

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

6

最后,把NSTextAttachment添加到完整字符串中

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

7

这样就可以了

在属性字符串中放入超链接

网页链接和其他属性字符串的属性一样,你可以在字符串的任意范围添加NSAttributedStringKey.link,并附带一个URL用于点击链接时展示。

let quote = "Haters gonna hate"
let font = UIFont.systemFont(ofSize: 72)
let attributes = [NSAttributedStringKey.font: font]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

8

注意:这里只创建了链接,并没有添加格式,链接会默认显示成蓝色加下划线。你可以根据需要设置文本样式的linkTextAttributes属性。

作者: Paul Hudson

链接: https://www.hackingwithswift.com/articles/113/nsattributedstring-by-example

翻译: cocoachina

(1)

本文由 投稿者 创作,文章地址:https://blog.isoyu.com/archives/nsattributedstring-yingyonganli.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:8 月 29, 2018 at 09:47 下午

热评文章

发表回复

[必填]

我是人?

提交后请等待三秒以免造成未提交成功和重复