Attributed Text 是 iOS SDK 的一种机制,由 NSAttributedString 和 NSMutableAttributedString 类表示,允许将多种样式应用于单个文本字符串的不同部分。与普通的 NSString 不同,Attributed String 不仅存储字符,还为每个范围存储属性字典:字体、颜色、行间距、阴影和对齐。根据 Apple Developer Documentation,Attributed String 是在 UILabel、UITextView 和 UITextField 中显示格式化文本的基础。这是无需 WebKit 或第三方库即可样式化文本的标准方式。
要点
NSAttributedString 是 Foundation 框架的一个类,表示一个带有绑定到字符范围的命名属性集的字符串。每个属性是一个键值对:键由常量定义(NSFontAttributeName、NSForegroundColorAttributeName),值由相应的对象定义(UIFont、UIColor)。属性通过 NSRange 应用于字符范围。
该类在所有 Apple 平台上都可用:iOS(2.0+)、macOS、tvOS、watchOS。NSAttributedString 是不可变的 — 创建后其属性是固定的。对于动态更改,使用 NSMutableAttributedString,它继承自 NSAttributedString 并添加了 setAttributes、addAttributes、addAttribute、removeAttribute 方法。
NSString 是一个没有样式信息的简单字符字符串。通过 text 属性传递给 UILabel 的任何文本都将以单一字体、颜色和大小显示。通过 attributedText 传递的 NSAttributedString 允许每个字符拥有自己的属性集。UILabel、UITextView 和 UITextField 自动识别 NSAttributedString 并根据属性渲染文本。
在内部,NSAttributedString 存储一个带有文本的 NSString 和一个属性范围数组。每个范围由一个 NSRange 结构和一个属性字典表示。渲染时,系统遍历范围并将相应的属性应用于每个部分。效率取决于属性切换的次数 — 短片段上的频繁更改会增加渲染时间。
NSAttributedString 的属性 是在 UIKit(iOS)和 AppKit(macOS)中定义的常量,每个常量对应于文本视觉格式化的特定方面。所有属性都是 NSAttributedString.Key 字符串,其值是特定类的对象。属性分为字符属性(影响字符)和段落属性(影响段落)。
字符属性包括 字体(NSFontAttributeName)、文本颜色(NSForegroundColorAttributeName)、背景颜色(NSBackgroundColorAttributeName)、下划线(NSUnderlineStyleAttributeName)、删除线(NSStrikethroughStyleAttributeName)、阴影(NSShadowAttributeName)。段落属性通过 NSParagraphStyleAttributeName 设置,控制对齐、缩进、行间距和制表符。
NSLinkAttributeName 在文本中创建可点击链接:值是 URL 或字符串。如果启用了交互,UITextView 会自动处理此类链接。NSAttachmentAttributeName 允许嵌入 NSTextAttachment — 文本中作为内联元素显示的图像。这用于创建带有图标、表情符号或字符串内自定义视图的文本。
每个 NSAttributedString 属性都有一个严格类型的值。让我们看看 iOS 开发中最常用的属性。字体由 UIFont 对象设置,颜色由 UIColor 设置,行间距通过 NSMutableParagraphStyle 设置,允许在一个对象中配置对齐、缩进和间距。
| 属性键 | 值类型 | 用途 |
|---|---|---|
| NSFontAttributeName | UIFont | 文本字体 |
| NSForegroundColorAttributeName | UIColor | 文本颜色 |
| NSBackgroundColorAttributeName | UIColor | 文本下方背景颜色 |
| NSUnderlineStyleAttributeName | NSNumber (Int) | 下划线样式 |
| NSParagraphStyleAttributeName | NSParagraphStyle | 段落设置 |
| NSKernAttributeName | NSNumber (Float) | 字间距 |
NSParagraphStyle 是段落属性的容器:alignment、lineSpacing、paragraphSpacing、firstLineHeadIndent、lineBreakMode、minimumLineHeight 等。要更改这些参数,创建一个 NSMutableParagraphStyle,配置所需的属性,然后将对象作为 NSParagraphStyleAttributeName 属性的值传递。这是在 NSAttributedString 中控制行间距的唯一方式。
NSShadow 允许为文本添加阴影:shadowOffset、shadowBlurRadius、shadowColor 参数设置阴影的偏移、模糊和颜色。下划线和删除线属性接受样式的组合:NSUnderlineStyle.single、.double、.thick、.patternDash、.patternDot。要精确控制线条的粗细和颜色,使用 NSUnderlineColorAttributeName 和 NSStrikethroughColorAttributeName。
在 Swift 中创建 NSAttributedString 通过指定文本和属性字典的初始化器完成,或者通过 NSMutableAttributedString 逐步应用样式完成。基本方法 — 为整个文本定义属性字典,然后为各个范围添加或修改属性。
一个简单的例子 — 为整个字符串设置 字体、颜色和对齐。属性字典传递给 NSAttributedString 的初始化器。字典的键是 NSAttributedString.Key 常量,值是相应的 UIKit 对象。这是整个文本统一格式化的基本变体。
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 16),
.foregroundColor: UIColor.darkGray,
.paragraphStyle: let style = NSMutableParagraphStyle()
style.alignment = .center
style.lineSpacing = 4
return style
]
let attributedString = NSAttributedString(
string: "Hello world",
attributes: attributes
)
label.attributedText = attributedString
文本将以 systemFont 16 字体、深灰色、居中对齐和 4pt 行间距显示。这种方法适用于静态标题和按钮。
NSMutableAttributedString 允许将不同的样式应用于文本的不同部分。addAttribute 方法向范围添加一个属性,addAttributes — 属性字典。setAttributes 方法将范围的所有属性替换为新的。这是创建带有高亮文本的主要工具。
let text = "Price: 1999 rubles"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.foregroundColor,
value: UIColor.green, range: NSRange(location: 6, length: 4))
attributed.addAttribute(.font,
value: UIFont.boldSystemFont(ofSize: 20), range: NSRange(location: 6, length: 4))
label.attributedText = attributed
单词 “1999” 将是绿色和粗体,其余文本 — 标准。NSRange 是手动计算的 — 正确计算字符长度很重要,尤其是在处理表情符号和复合 Unicode 字符时。
NSMutableAttributedString 提供了用于动态更改文本和属性的方法:append、insert、replace、delete、setAttributes、addAttribute、removeAttribute、enumerateAttributes。这允许从不同来源构建文本、组合样式并响应用户界面事件。
与不可变的 NSAttributedString 不同,可变版本支持在不创建新对象的情况下更改内容。这对于文本编辑器、聊天和表单至关重要,用户可以编辑文本而样式必须保留。
在消息应用程序中,每条消息包含用户名(粗体字体)、消息文本(普通)、时间(灰色颜色)。NSMutableAttributedString 允许一次性构建这样的字符串,以正确的顺序使用相应的属性添加部分。
let result = NSMutableAttributedString()
let name = NSAttributedString(string: "Anna: ",
attributes: [.font: UIFont.boldSystemFont(ofSize: 15)])
let message = NSAttributedString(string: "Hello, how are you?",
attributes: [.font: UIFont.systemFont(ofSize: 15)])
let time = NSAttributedString(string: " 12:30",
attributes: [.foregroundColor: UIColor.gray])
result.append(name)
result.append(message)
result.append(time)
label.attributedText = result
结果 — 一个具有三个样式部分的字符串。Append 自动正确计算 NSRange,位置不需要手动计算。这种方法可扩展到任意数量的片段。
enumerateAttributes(in:options:using:) 方法遍历指定间隔中的所有属性范围。这对于分析格式很有用:查找所有链接、更改某些属性的颜色或将文本导出为 HTML。在闭包中传递当前部分的属性字典和 NSRange。
UIKit 中所有用于显示文本的基本 UI 组件都通过 attributedText 属性支持 NSAttributedString。UILabel 显示静态样式文本,UITextView 支持编辑和链接,UITextField 分别为占位符和输入文本单独接受属性。
UILabel 是显示样式文本的最轻量级组件。它支持所有字符属性,但不会自动处理可点击链接(为此需要 UITextView)。UILabel 非常适合标题、标签和带有格式的短文本。
UITextView 处理 NSLinkAttributeName 并将链接显示为交互元素。要启用此功能,请设置 isSelectable = true 和 isEditable = false。单击链接时,委托收到 textView(_:shouldInteractWith:in:interaction:) 调用。UITextView 还支持用于文本内图像的 NSTextAttachment。
let text = "Details on developer.apple.com"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.link,
value: URL(string: "https://developer.apple.com")!,
range: NSRange(location: 0, length: text.count))
textView.attributedText = attributed
textView.isSelectable = true
textView.isEditable = false
配置 isSelectable 和 isEditable 后,文本区域的行为类似于静态文本块,但链接保持活动状态。UITextViewDelegate 委托管理单击时的行为。
Core Text 是 Apple 的低级文本渲染框架,直接与 NSAttributedString 一起工作。与 UIKit 不同,Core Text 不直接使用 NSAttributedString 作为要显示的对象,而是将其转换为 CTFramesetter,然后转换为 CTFrame,并在 Core Graphics 上下文中渲染。这提供了对行和字形放置的完全控制。
使用 Core Text 适用于自定义文本布局:列、图像环绕、文本旋转、非标准换行。Core Text 的 NSMutableParagraphStyle 包含 UIKit 中没有的属性:kCTParagraphStyleSpecifierMaximumLineSpacing、kCTParagraphStyleSpecifierLineBreakMode 带有附加模式。
NSAttributedString 在 UIKit 和 Core Text 之间无缝传输,因为两个框架使用相同的类型。UIKit 属性(NSFontAttributeName、NSForegroundColorAttributeName)被 Core Text 自动识别,反之亦然 — Core Text 属性(kCTFontAttributeName)被 UIKit 读取。这允许在同一个 NSAttributedString 对象上使用 UIKit 进行简单任务,使用 Core Text 进行自定义渲染。
常见问题
NSString 只存储文本而没有样式信息。NSAttributedString 为每个字符范围补充一个属性字典。通过 text 属性传递给 UILabel 时,NSString 显示为纯文本。通过 attributedText 属性传递 NSAttributedString 时,所有属性都被应用:同一字符串中不同的字体、颜色和间距。
使用带属性字典的 addAttributes(_:range:) 方法:addAttributes([.font: font, .foregroundColor: color], range: range)。要添加或更改一个属性,使用 addAttribute(_:value:range:)。setAttributes 方法将范围内所有现有属性替换为新属性。
创建一个 NSMutableParagraphStyle,设置 lineSpacing 属性,然后将其作为 NSParagraphStyleAttributeName 属性的值传递。为了完全控制,还可以使用 minimumLineHeight、maximumLineHeight、paragraphSpacing、lineBreakMode 和 alignment。ParagraphStyle 是控制行间距的唯一方式。
是的,SwiftUI 在 iOS 15+ 中通过 Text(attributedString:) 支持 NSAttributedString。在较旧版本中,使用带有 UILabel 或 UITextView 的 UIViewRepresentable。SwiftUI 还提供了自己的 AttributedString 类型(SwiftUI,不是 Foundation),用于使用类似 Markdown 的语法进行声明式格式化。
使用 boundingRect(with:options:context:) 方法,它返回显示具有指定属性的字符串所需的 CGRect。options: [.usesLineFragmentOrigin, .usesFontLeading] 参数考虑了行间距和字体度量。对于行数受限的 UILabel,使用 sizeThatFits。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。