NSAttributedString — 是 iOS SDK 中 Foundation 框架的一个类,表示一个带有应用于单个字符或文本范围的格式化属性集的字符串。与普通的 NSString 不同,NSAttributedString 不仅存储 Unicode 字符,还为字符串的每个片段存储属性字典(字体、颜色、字符间距、对齐方式)。根据 Apple Developer Documentation (2026),NSAttributedString 是 iOS 所有 UI 组件中显示格式化文本的基础。
要点
NSAttributedString — 是用于处理格式化文本的 iOS/macOS 基础类。它通过向字符串添加属性来扩展 NSString 的功能——一个键值对字典,其中键是 NSAttributedStringKey 常量(例如 .font、.foregroundColor),值是对应的对象(UIFont、UIColor)。字符串中的每个字符都可以有自己的属性集,从而允许在一个字符串中实现混合格式化。
NSAttributedString 的架构基于属性范围(attribute runs)的概念。如果为字符范围 0..5 设置了属性 .font = UIFont.boldSystemFont(ofSize: 16),则该范围内的所有字符将以粗体字体显示。其余字符可以具有不同的字体或根本没有属性。在显示属性字符串时,UIKit 系统会组合不同范围的特性并统一渲染文本。
NSAttributedString 是不可变的——创建后,其属性和内容无法更改。对于修改,存在子类 NSMutableAttributedString,它提供了添加、删除和修改任意范围内属性的方法。这种区别对于多线程很重要:不可变的 NSAttributedString 是线程安全的,而 NSMutableAttributedString 则不是。
NSAttributedString 支持大约 40 个在 NSAttributedStringKey 中定义的标准属性。每个属性影响文本外观的特定方面:字体、颜色、位置、下划线、阴影、字符间距、段落样式和超链接。要设置属性,请使用 NSAttributedStringKey 常量,并为其分配相应类型的对象。
| 属性键 | 值类型 | 用途 |
|---|---|---|
| .font | UIFont | 字体和文本大小 |
| .foregroundColor | UIColor | 文本颜色 |
| .backgroundColor | UIColor | 文本下方背景色 |
| .paragraphStyle | NSParagraphStyle | 对齐、行间距、缩进 |
| .kern | NSNumber (Float) | 字符间距(字距调整) |
| .underlineStyle | NSUnderlineStyle (Int) | 下划线样式(single、double、thick、pattern) |
| .strikethroughStyle | NSUnderlineStyle (Int) | 删除线样式 |
| .link | NSURL | 交互式超链接的 URL |
| .shadow | NSShadow | 带有 offset、blurRadius 和颜色的文本阴影 |
| .baselineOffset | NSNumber (Float) | 文本相对于基线的偏移 |
NSMutableParagraphStyle — 管理段落视觉特性的对象:对齐(.alignment:.left、.center、.right、.justified)、行间距(.lineSpacing)、段落间距(.paragraphSpacing)、首行缩进(.firstLineHeadIndent)、左右缩进(.headIndent、.tailIndent)和文本方向(.baseWritingDirection)。如果需要整个段落具有相同的格式,ParagraphStyle 将应用于包含换行符的范围。
创建 NSAttributedString 通过接受字符串和属性字典的初始化器完成。属性应用于整个字符串。对于混合格式化(字符串不同部分具有不同属性),使用 NSMutableAttributedString,然后向特定范围添加属性。Objective-C 使用 NSAttributedStringKey: UIFont 字典,而 Swift 使用类型安全的 [NSAttributedString.Key: Any] 字典。
let plainText = "Hello, Swift!"
// Create with uniform attributes for the entire string
let attributes: [NSAttributedString.Key: Any] = [
NSAttributedString.Key.font:
UIFont.systemFont(ofSize: 18),
NSAttributedString.Key.foregroundColor:
UIColor.darkText,
NSAttributedString.Key.kern: 1.5
]
let attributedString =
NSAttributedString(string: plainText,
attributes: attributes)
示例演示了通过 NSMutableParagraphStyle 格式化段落。设置居中对齐、8 磅行间距、段落后 12 磅间距。ParagraphStyle 以 .paragraphStyle 键添加到属性字典中。NSAttributedString 会复制传入的 paragraphStyle,因此在创建字符串后可以修改它,而不会影响已创建的字符串。
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.center
paragraphStyle.lineSpacing = 8.0
paragraphStyle.paragraphSpacing = 12.0
paragraphStyle.firstLineHeadIndent = 20.0
let attributed = NSAttributedString(
string: "Centered paragraph with spacing",
attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle])
NSMutableAttributedString — 是 NSAttributedString 的子类,允许在创建后修改内容和属性。主要方法:addAttribute(_:value:range:) 用于向范围添加一个属性;addAttributes(_:range:) 用于添加多个属性;setAttributes(_:range:) 用于替换范围内的所有属性;removeAttribute(_:range:) 用于删除属性;replaceCharacters(in:with:) 用于替换文本。
addAttribute 和 addAttributes 将属性添加到现有属性中,而不会删除已设置的属性。如果范围内已存在具有相同键的属性,则替换其值。setAttributes 完全替换范围的属性字典——所有先前设置的属性都将被删除。这在顺序格式化一个字符串时很重要:addAttributes 更安全,因为它不会重置已设置的字体和颜色。
范围 (NSRange) 由结构体 NSRange(location: 0, length: 5) 定义。location — 起始索引(从 0 开始),length — 字符数。如果范围超出字符串边界,NSMutableAttributedString 会生成 NSRangeException 异常。为了安全地处理范围,可以使用 Foundation 中的 NSRange 方法,如 NSIntersectionRange 和 NSUnionRange。
let attributed = NSMutableAttributedString(
string: "Bold and red text here")
// Apply bold font to first 9 characters
let boldRange = NSRange(location: 0, length: 9)
attributed.addAttribute(
NSAttributedString.Key.font,
value: UIFont.boldSystemFont(ofSize: 16),
range: boldRange)
// Apply red color to characters 13-16 ("text")
let redRange = NSRange(location: 13, length: 4)
attributed.addAttribute(
NSAttributedString.Key.foregroundColor,
value: UIColor.red,
range: redRange)
// Apply underline to the entire string
let fullRange = NSRange(location: 0,
length: attributed.length)
attributed.addAttribute(
NSAttributedString.Key.underlineStyle,
value: NSUnderlineStyle.single.rawValue,
range: fullRange)
最常见的显示方式 NSAttributedString — 将其分配给 UILabel 的 attributedText 属性。与 text 属性不同,attributedText 使用属性进行渲染,支持混合格式化。重要提示:如果设置了 attributedText,UILabel 会忽略 font、textColor、textAlignment 属性——所有视觉特性都来自 NSAttributedString 的属性。
let label = UILabel()
label.numberOfLines = 0
let fullText = NSMutableAttributedString(
string: "Price: $24.99 per month")
// Format "Price:" label with bold font
let priceLabelRange = NSRange(
location: 0, length: 6)
fullText.addAttribute(
NSAttributedString.Key.font,
value: UIFont.boldSystemFont(ofSize: 16),
range: priceLabelRange)
// Format "$24.99" with green color
let amountRange = NSRange(
location: 7, length: 6)
fullText.addAttribute(
NSAttributedString.Key.foregroundColor,
value: UIColor.systemGreen(),
range: amountRange)
fullText.addAttribute(
NSAttributedString.Key.font,
value: UIFont.boldSystemFont(ofSize: 22),
range: amountRange)
// Apply gray color to "per month" text
let periodRange = NSRange(
location: 14, length: 9)
fullText.addAttribute(
NSAttributedString.Key.foregroundColor,
value: UIColor.secondaryLabel,
range: periodRange)
label.attributedText = fullText
UITextView 支持 NSAttributedString 中的交互式链接。带有 NSURL 的 .link 属性使文本可点击。为了处理点击,使用 UITextViewDelegate 委托,通过方法 textView(_:shouldInteractWith:in:interaction:)。UITextView 还支持文本选择和 UIMenuController 用于标准操作(复制、搜索)。
NSAttributedString 支持通过 NSAttributedString.DocumentType 从 HTML 和 RTF 进行转换。要加载 HTML,使用带有 documentAttributes 参数的初始化器:NSAttributedString(data: htmlData, options: [.documentType: .html], documentAttributes: nil)。同样适用于 RTF:.rtf 或 .rtfd。这种机制对于无需 WebView 显示 HTML 内容很有用。
要导出为 HTML,使用带有范围和文档类型的方法 data(from:documentAttributes:)。HTML 导出:try attributedString.data(from: fullRange, documentAttributes: [.documentType: .html])。获取的数据可以保存到文件、发送到服务器或在 WebView 中显示。导出时会保留字体、颜色、对齐方式、列表——所有格式化属性都会转换为 CSS 样式。
对 RTF 的支持对于 macOS 应用程序尤其重要,因为 RTF 是富文本的标准格式。iOS 也支持读取和写入 RTF,但不会将其作为主要格式使用。RTF 和 RTFD 之间的区别:RTFD 包含打包在目录中的嵌套资源(图像)。NSAttributedString 可以通过统一接口处理这两种格式。
let htmlString = "<p><b>Bold<\/b> and <i>italic<\/i><\/p>"
guard let htmlData = htmlString.data(
using: String.Encoding.utf8) else { return }
let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
NSAttributedString.DocumentReadingOptionKey.documentType:
NSAttributedString.DocumentType.html
]
let attributedFromHTML =
try? NSAttributedString(
data: htmlData,
options: options,
documentAttributes: nil)
常见问题
NSString 仅存储 Unicode 字符序列,不包含任何格式化信息。NSAttributedString 存储字符,并为每个子范围包含一个属性字典(字体、颜色、样式)。在显示 NSAttributedString 时,UIKit 会使用这些属性进行渲染,创建格式化文本。
最常见的原因——使用了 text 属性而不是 attributedText。通过 text 赋值时,所有属性都会被忽略。第二个原因:设置 attributedText 后,您更改了 UILabel 的 font、textColor 或 textAlignment——这些更改会重置 attributedText。对于格式化文本,请仅使用 attributedText。
创建一个 NSMutableAttributedString,并为每个具有不同字体的部分调用 addAttribute(.font, value: boldFont, range: boldRange)。每次调用仅将属性应用于指定范围。其余字符保留标准字体或先前设置的其他字体。这样就创建了具有不同字体的属性范围(attribute runs)。
是的,NSAttributedString 能正确处理多行文本,包括换行符 ( )。UITextView 和 UILabel(使用 numberOfLines = 0)会自动将文本换行。NSMutableParagraphStyle 为每个段落独立管理行间距、缩进和对齐。
对每个颜色范围使用带有 .foregroundColor 属性的 NSMutableAttributedString。对于红色文本:addAttribute(.foregroundColor, value: UIColor.red, range: firstRange)。对于蓝色:addAttribute(.foregroundColor, value: UIColor.blue, range: secondRange)。颜色仅应用于指定字符范围。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。