NSAttributedString — 是什么,文本格式化和 iOS 中的属性

作者: IT Sectr 发布日期: 2026-07-23 阅读时间: 9 分钟

NSAttributedString — 是 iOS SDK 中 Foundation 框架的一个类,表示一个带有应用于单个字符或文本范围的格式化属性集的字符串。与普通的 NSString 不同,NSAttributedString 不仅存储 Unicode 字符,还为字符串的每个片段存储属性字典(字体、颜色、字符间距、对齐方式)。根据 Apple Developer Documentation (2026),NSAttributedString 是 iOS 所有 UI 组件中显示格式化文本的基础。

要点

  • NSAttributedString — 带有属性的不可变字符串,每个字符或范围对应一个 NSAttributedStringKey 属性字典
  • NSMutableAttributedString — 可变版本,具有 addAttribute、setAttributes、replaceCharacters 方法,可在运行时修改属性
  • 主要属性:.font、.foregroundColor、.paragraphStyle、.kern、.underlineStyle、.strikethroughStyle、.link、.backgroundColor
  • NSMutableParagraphStyle — 用于设置对齐、行间距、缩进和文本方向的辅助对象
  • UILabel、UITextView、UITextField 支持 attributedText 以显示属性字符串

什么是 NSAttributedString?

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 常量,并为其分配相应类型的对象。

属性键值类型用途
.fontUIFont字体和文本大小
.foregroundColorUIColor文本颜色
.backgroundColorUIColor文本下方背景色
.paragraphStyleNSParagraphStyle对齐、行间距、缩进
.kernNSNumber (Float)字符间距(字距调整)
.underlineStyleNSUnderlineStyle (Int)下划线样式(single、double、thick、pattern)
.strikethroughStyleNSUnderlineStyle (Int)删除线样式
.linkNSURL交互式超链接的 URL
.shadowNSShadow带有 offset、blurRadius 和颜色的文本阴影
.baselineOffsetNSNumber (Float)文本相对于基线的偏移

NSParagraphStyle — 段落格式化

NSMutableParagraphStyle — 管理段落视觉特性的对象:对齐(.alignment:.left、.center、.right、.justified)、行间距(.lineSpacing)、段落间距(.paragraphSpacing)、首行缩进(.firstLineHeadIndent)、左右缩进(.headIndent、.tailIndent)和文本方向(.baseWritingDirection)。如果需要整个段落具有相同的格式,ParagraphStyle 将应用于包含换行符的范围。

如何在代码中创建 NSAttributedString

创建 NSAttributedString 通过接受字符串和属性字典的初始化器完成。属性应用于整个字符串。对于混合格式化(字符串不同部分具有不同属性),使用 NSMutableAttributedString,然后向特定范围添加属性。Objective-C 使用 NSAttributedStringKey: UIFont 字典,而 Swift 使用类型安全的 [NSAttributedString.Key: Any] 字典。

swift
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 创建

示例演示了通过 NSMutableParagraphStyle 格式化段落。设置居中对齐、8 磅行间距、段落后 12 磅间距。ParagraphStyle 以 .paragraphStyle 键添加到属性字典中。NSAttributedString 会复制传入的 paragraphStyle,因此在创建字符串后可以修改它,而不会影响已创建的字符串。

swift
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 和属性修改

NSMutableAttributedString — 是 NSAttributedString 的子类,允许在创建后修改内容和属性。主要方法:addAttribute(_:value:range:) 用于向范围添加一个属性;addAttributes(_:range:) 用于添加多个属性;setAttributes(_:range:) 用于替换范围内的所有属性;removeAttribute(_:range:) 用于删除属性;replaceCharacters(in:with:) 用于替换文本。

addAttributeaddAttributes 将属性添加到现有属性中,而不会删除已设置的属性。如果范围内已存在具有相同键的属性,则替换其值。setAttributes 完全替换范围的属性字典——所有先前设置的属性都将被删除。这在顺序格式化一个字符串时很重要:addAttributes 更安全,因为它不会重置已设置的字体和颜色。

范围 (NSRange) 由结构体 NSRange(location: 0, length: 5) 定义。location — 起始索引(从 0 开始),length — 字符数。如果范围超出字符串边界,NSMutableAttributedString 会生成 NSRangeException 异常。为了安全地处理范围,可以使用 Foundation 中的 NSRange 方法,如 NSIntersectionRangeNSUnionRange

swift
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)

在 UILabel 中显示属性字符串的示例

最常见的显示方式 NSAttributedString — 将其分配给 UILabel 的 attributedText 属性。与 text 属性不同,attributedText 使用属性进行渲染,支持混合格式化。重要提示:如果设置了 attributedText,UILabel 会忽略 font、textColor、textAlignment 属性——所有视觉特性都来自 NSAttributedString 的属性。

swift
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 中显示交互式链接

UITextView 支持 NSAttributedString 中的交互式链接。带有 NSURL 的 .link 属性使文本可点击。为了处理点击,使用 UITextViewDelegate 委托,通过方法 textView(_:shouldInteractWith:in:interaction:)。UITextView 还支持文本选择和 UIMenuController 用于标准操作(复制、搜索)。

将 NSAttributedString 转换为 HTML 和 RTF

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 可以通过统一接口处理这两种格式。

swift
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 和 NSAttributedString 有什么区别?

NSString 仅存储 Unicode 字符序列,不包含任何格式化信息。NSAttributedString 存储字符,并为每个子范围包含一个属性字典(字体、颜色、样式)。在显示 NSAttributedString 时,UIKit 会使用这些属性进行渲染,创建格式化文本。

为什么 UILabel 不显示 NSAttributedString 的属性?

最常见的原因——使用了 text 属性而不是 attributedText。通过 text 赋值时,所有属性都会被忽略。第二个原因:设置 attributedText 后,您更改了 UILabel 的 font、textColor 或 textAlignment——这些更改会重置 attributedText。对于格式化文本,请仅使用 attributedText。

如何将不同字体应用于一个字符串?

创建一个 NSMutableAttributedString,并为每个具有不同字体的部分调用 addAttribute(.font, value: boldFont, range: boldRange)。每次调用仅将属性应用于指定范围。其余字符保留标准字体或先前设置的其他字体。这样就创建了具有不同字体的属性范围(attribute runs)。

NSAttributedString 是否支持多行文本?

是的,NSAttributedString 能正确处理多行文本,包括换行符 ( )。UITextView 和 UILabel(使用 numberOfLines = 0)会自动将文本换行。NSMutableParagraphStyle 为每个段落独立管理行间距、缩进和对齐。

如何在一个字符串中创建不同颜色的彩色文本?

对每个颜色范围使用带有 .foregroundColor 属性的 NSMutableAttributedString。对于红色文本:addAttribute(.foregroundColor, value: UIColor.red, range: firstRange)。对于蓝色:addAttribute(.foregroundColor, value: UIColor.blue, range: secondRange)。颜色仅应用于指定字符范围。

总结

  • NSAttributedString — 具有格式化属性(字体、颜色、样式)的字符串,属性以字典形式存储在每个字符范围中
  • NSMutableAttributedString — 可变版本,具有 addAttribute、setAttributes 和 removeAttribute 方法,用于动态格式化
  • 主要属性:.font、.foregroundColor、.paragraphStyle、.kern、.underlineStyle、.strikethroughStyle、.link、.shadow、.baselineOffset
  • NSMutableParagraphStyle 管理段落的对齐、行间距、缩进和文本方向
  • UILabel、UITextView、UITextField 通过 attributedText 属性支持显示格式化文本
  • HTML/RTF 转换 — NSAttributedString 通过 documentType 支持格式化文本的导入和导出

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读